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
@@ -244,8 +244,8 @@ def list_cloud(name: Optional[str], cloud_id: Optional[str], max_items: int,) ->
|
|
244
244
|
)
|
245
245
|
|
246
246
|
|
247
|
-
@cloud_cli.group("
|
248
|
-
def
|
247
|
+
@cloud_cli.group("resource", help="Manage the configuration for a cloud resource.")
|
248
|
+
def cloud_resource_group() -> None:
|
249
249
|
pass
|
250
250
|
|
251
251
|
|
@@ -254,68 +254,68 @@ def cloud_config_group() -> None:
|
|
254
254
|
pass
|
255
255
|
|
256
256
|
|
257
|
-
@
|
257
|
+
@cloud_resource_group.command(
|
258
258
|
name="create",
|
259
|
-
help="Create a new cloud
|
259
|
+
help="Create a new cloud resource in an existing cloud.",
|
260
260
|
cls=AnyscaleCommand,
|
261
|
-
example=command_examples.
|
261
|
+
example=command_examples.CLOUD_RESOURCE_CREATE_EXAMPLE,
|
262
262
|
is_alpha=True,
|
263
263
|
)
|
264
264
|
@click.option(
|
265
265
|
"--cloud",
|
266
|
-
help="The name of the cloud to
|
266
|
+
help="The name of the cloud to add the new resource to.",
|
267
267
|
type=str,
|
268
268
|
required=True,
|
269
269
|
)
|
270
270
|
@click.option(
|
271
271
|
"--file",
|
272
272
|
"-f",
|
273
|
-
help="Path to a YAML file defining the cloud
|
273
|
+
help="Path to a YAML file defining the cloud resource. Schema: https://docs.anyscale.com/reference/cloud/#cloudresource.",
|
274
274
|
required=True,
|
275
275
|
)
|
276
276
|
@click.option(
|
277
277
|
"--skip-verification",
|
278
278
|
is_flag=True,
|
279
279
|
default=False,
|
280
|
-
help="Skip cloud
|
280
|
+
help="Skip cloud resource verification.",
|
281
281
|
)
|
282
282
|
@click.option(
|
283
283
|
"--yes", "-y", is_flag=True, default=False, help="Skip asking for confirmation."
|
284
284
|
)
|
285
|
-
def
|
285
|
+
def cloud_resource_create(
|
286
286
|
cloud: str, file: str, skip_verification: bool, yes: bool,
|
287
287
|
) -> None:
|
288
288
|
try:
|
289
|
-
CloudController().
|
289
|
+
CloudController().create_cloud_resource(cloud, file, skip_verification, yes)
|
290
290
|
except click.ClickException as e:
|
291
291
|
print(e)
|
292
292
|
|
293
293
|
|
294
|
-
@
|
294
|
+
@cloud_resource_group.command(
|
295
295
|
name="delete",
|
296
|
-
help="Remove a cloud
|
296
|
+
help="Remove a cloud resource from an existing cloud.",
|
297
297
|
cls=AnyscaleCommand,
|
298
|
-
example=command_examples.
|
298
|
+
example=command_examples.CLOUD_RESOURCE_DELETE_EXAMPLE,
|
299
299
|
is_alpha=True,
|
300
300
|
)
|
301
301
|
@click.option(
|
302
302
|
"--cloud",
|
303
|
-
help="The name of the cloud to remove the
|
303
|
+
help="The name of the cloud to remove the resource from.",
|
304
304
|
type=str,
|
305
305
|
required=True,
|
306
306
|
)
|
307
307
|
@click.option(
|
308
|
-
"--
|
309
|
-
help="The name of the
|
308
|
+
"--resource",
|
309
|
+
help="The name of the cloud resource to remove.",
|
310
310
|
type=str,
|
311
311
|
required=True,
|
312
312
|
)
|
313
313
|
@click.option(
|
314
314
|
"--yes", "-y", is_flag=True, default=False, help="Skip asking for confirmation."
|
315
315
|
)
|
316
|
-
def
|
316
|
+
def cloud_resource_delete(cloud: str, resource: str, yes: bool,) -> None:
|
317
317
|
try:
|
318
|
-
CloudController().
|
318
|
+
CloudController().remove_cloud_resource(cloud, resource, yes)
|
319
319
|
except click.ClickException as e:
|
320
320
|
print(e)
|
321
321
|
|
@@ -361,7 +361,7 @@ def cloud_deployment_delete(cloud: str, deployment: str, yes: bool,) -> None:
|
|
361
361
|
@click.option(
|
362
362
|
"--resources-file",
|
363
363
|
"-f",
|
364
|
-
help="EXPERIMENTAL: Path to a YAML file defining a list of cloud resources. Schema: https://docs.anyscale.com/reference/cloud/#
|
364
|
+
help="EXPERIMENTAL: Path to a YAML file defining a list of cloud resources. Schema: https://docs.anyscale.com/reference/cloud/#cloudresource.",
|
365
365
|
required=False,
|
366
366
|
)
|
367
367
|
@click.option(
|
@@ -387,7 +387,7 @@ def cloud_update( # noqa: PLR0913
|
|
387
387
|
"were both provided. Please only provide one of these two arguments."
|
388
388
|
)
|
389
389
|
if resources_file:
|
390
|
-
CloudController().
|
390
|
+
CloudController().update_cloud_resources(
|
391
391
|
cloud_name=cloud_name or name,
|
392
392
|
cloud_id=cloud_id,
|
393
393
|
resources_file=resources_file,
|
@@ -1337,14 +1337,16 @@ def get_cloud(
|
|
1337
1337
|
log.error("Cloud not found.")
|
1338
1338
|
return
|
1339
1339
|
|
1340
|
-
# Include all cloud
|
1341
|
-
|
1340
|
+
# Include all cloud resources for the cloud.
|
1341
|
+
cloud_resources = CloudController().get_formatted_cloud_resources(
|
1342
|
+
cloud_id=cloud.id
|
1343
|
+
)
|
1342
1344
|
result = {
|
1343
1345
|
"name": cloud.name,
|
1344
1346
|
"id": cloud.id,
|
1345
1347
|
"created_at": cloud.created_at,
|
1346
1348
|
"is_default": cloud.is_default,
|
1347
|
-
"
|
1349
|
+
"resources": cloud_resources,
|
1348
1350
|
}
|
1349
1351
|
|
1350
1352
|
if output:
|
@@ -550,12 +550,12 @@ collaborators:
|
|
550
550
|
"""
|
551
551
|
|
552
552
|
|
553
|
-
|
554
|
-
$ anyscale cloud
|
555
|
-
Successfully created cloud
|
553
|
+
CLOUD_RESOURCE_CREATE_EXAMPLE = """\
|
554
|
+
$ anyscale cloud resource create --cloud my-cloud --file new-cloud-resource.yaml
|
555
|
+
Successfully created cloud resource my-new-resource in cloud my-cloud.
|
556
556
|
|
557
|
-
$ cat new-cloud-
|
558
|
-
name: my-new-
|
557
|
+
$ cat new-cloud-resource.yaml
|
558
|
+
name: my-new-resource
|
559
559
|
provider: AWS
|
560
560
|
compute_stack: VM
|
561
561
|
region: us-west-2
|
@@ -575,11 +575,11 @@ aws_config:
|
|
575
575
|
memorydb_cluster_name: my-memorydb-cluster
|
576
576
|
"""
|
577
577
|
|
578
|
-
|
579
|
-
$ anyscale cloud
|
578
|
+
CLOUD_RESOURCE_DELETE_EXAMPLE = """\
|
579
|
+
$ anyscale cloud resource delete --cloud my-cloud --resource my-resource
|
580
580
|
Output
|
581
|
-
Please confirm that you would like to remove
|
582
|
-
(anyscale +3.5s) Successfully removed
|
581
|
+
Please confirm that you would like to remove resource my-resource from cloud my-cloud. [y/N]: y
|
582
|
+
(anyscale +3.5s) Successfully removed resource my-resource from cloud my-cloud!
|
583
583
|
"""
|
584
584
|
|
585
585
|
CLOUD_GET_CLOUD_EXAMPLE = """\
|
@@ -589,7 +589,7 @@ name: my-cloud
|
|
589
589
|
created_at: 2022-10-18 05:12:13.335803+00:00
|
590
590
|
is_default: true
|
591
591
|
deployments:
|
592
|
-
-
|
592
|
+
- cloud_resource_id: cldrsrc_123
|
593
593
|
name: vm-aws-us-west-2
|
594
594
|
provider: AWS
|
595
595
|
compute_stack: VM
|
@@ -1,14 +1,25 @@
|
|
1
1
|
import click
|
2
2
|
|
3
|
+
from anyscale.commands.util import DeprecatedAnyscaleCommand
|
4
|
+
|
3
5
|
|
4
6
|
@click.command(
|
5
7
|
name="exec",
|
6
8
|
hidden=True,
|
7
9
|
help="[DEPRECATED] Execute shell commands in interactive cluster.",
|
8
10
|
context_settings={"ignore_unknown_options": True, "allow_extra_args": True,},
|
11
|
+
cls=DeprecatedAnyscaleCommand,
|
12
|
+
removal_date="2025-10-01",
|
13
|
+
deprecation_message="`anyscale exec` has been deprecated and no longer works on Anyscale",
|
14
|
+
alternative="use `anyscale job submit` to run your script as a job in a cluster",
|
9
15
|
)
|
10
16
|
def anyscale_exec() -> None:
|
17
|
+
"""Execute shell commands in interactive cluster.
|
18
|
+
|
19
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
20
|
+
Use 'anyscale job submit' to run your script as a job in a cluster.
|
21
|
+
"""
|
11
22
|
raise click.ClickException(
|
12
|
-
"
|
23
|
+
"`anyscale exec` has been deprecated and no longer works on Anyscale. "
|
13
24
|
"Please use `anyscale job submit` to run your script as a job in a cluster."
|
14
25
|
)
|
@@ -8,6 +8,7 @@ from typing import Any, Optional
|
|
8
8
|
import click
|
9
9
|
|
10
10
|
from anyscale.cli_logger import BlockLogger
|
11
|
+
from anyscale.commands.util import DeprecatedAnyscaleCommand
|
11
12
|
from anyscale.controllers.list_controller import ListController
|
12
13
|
|
13
14
|
|
@@ -25,26 +26,40 @@ def list_cli() -> None:
|
|
25
26
|
name="clouds",
|
26
27
|
help="[DEPRECATED] List the clouds currently available in your account.",
|
27
28
|
hidden=True,
|
29
|
+
cls=DeprecatedAnyscaleCommand,
|
30
|
+
removal_date="2025-10-01",
|
31
|
+
deprecation_message="`anyscale list clouds` has been deprecated",
|
32
|
+
alternative="use `anyscale cloud list` instead",
|
28
33
|
)
|
29
34
|
@click.option("--json", "show_json", help="Return the results in json", is_flag=True)
|
30
35
|
def list_clouds(show_json: bool) -> None:
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
"""List the clouds currently available in your account.
|
37
|
+
|
38
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
39
|
+
Use 'anyscale cloud list' instead.
|
40
|
+
"""
|
34
41
|
list_controller = ListController()
|
35
42
|
output = list_controller.list_clouds(json_format=show_json)
|
36
43
|
print(output)
|
37
44
|
|
38
45
|
|
39
46
|
@list_cli.command(
|
40
|
-
name="projects",
|
47
|
+
name="projects",
|
48
|
+
help="[DEPRECATED] List all accessible projects.",
|
49
|
+
hidden=True,
|
50
|
+
cls=DeprecatedAnyscaleCommand,
|
51
|
+
removal_date="2025-10-01",
|
52
|
+
deprecation_message="`anyscale list projects` has been deprecated",
|
53
|
+
alternative="use `anyscale project list` instead",
|
41
54
|
)
|
42
55
|
@click.option("--json", "show_json", help="Return the results in json", is_flag=True)
|
43
56
|
@click.pass_context
|
44
57
|
def project_list(ctx: Any, show_json: bool) -> None: # noqa: ARG001
|
45
|
-
|
46
|
-
|
47
|
-
|
58
|
+
"""List all accessible projects.
|
59
|
+
|
60
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
61
|
+
Use 'anyscale project list' instead.
|
62
|
+
"""
|
48
63
|
list_controller = ListController()
|
49
64
|
output = list_controller.list_projects(json_format=show_json)
|
50
65
|
print(output)
|
@@ -54,6 +69,10 @@ def project_list(ctx: Any, show_json: bool) -> None: # noqa: ARG001
|
|
54
69
|
name="sessions",
|
55
70
|
help="[DEPRECATED] List all clusters within the current project.",
|
56
71
|
hidden=True,
|
72
|
+
cls=DeprecatedAnyscaleCommand,
|
73
|
+
removal_date="2025-10-01",
|
74
|
+
deprecation_message="`anyscale list sessions` has been deprecated",
|
75
|
+
alternative="use `anyscale cluster list` instead",
|
57
76
|
)
|
58
77
|
@click.option(
|
59
78
|
"--name",
|
@@ -65,9 +84,11 @@ def project_list(ctx: Any, show_json: bool) -> None: # noqa: ARG001
|
|
65
84
|
@click.option("--all", help="List all clusters, including inactive ones.", is_flag=True)
|
66
85
|
@click.option("--json", "show_json", help="Return the results in json", is_flag=True)
|
67
86
|
def session_list(name: Optional[str], all: bool, show_json: bool) -> None: # noqa: A002
|
68
|
-
|
69
|
-
|
70
|
-
|
87
|
+
"""List all clusters within the current project.
|
88
|
+
|
89
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
90
|
+
Use 'anyscale cluster list' instead.
|
91
|
+
"""
|
71
92
|
list_controller = ListController()
|
72
93
|
output = list_controller.list_sessions(
|
73
94
|
name=name, show_all=all, json_format=show_json
|
@@ -79,7 +100,16 @@ def session_list(name: Optional[str], all: bool, show_json: bool) -> None: # no
|
|
79
100
|
name="ips",
|
80
101
|
help="[DEPRECATED] List IP addresses of head and worker nodes.",
|
81
102
|
context_settings={"ignore_unknown_options": True, "allow_extra_args": True,},
|
103
|
+
cls=DeprecatedAnyscaleCommand,
|
104
|
+
removal_date="2025-10-01",
|
105
|
+
deprecation_message="Listing IPs is not supported on Anyscale",
|
106
|
+
alternative="use the Anyscale console to view cluster node information",
|
82
107
|
)
|
83
108
|
def list_ips() -> None:
|
84
|
-
"""List IP addresses of head and worker nodes.
|
85
|
-
|
109
|
+
"""List IP addresses of head and worker nodes.
|
110
|
+
|
111
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
112
|
+
Listing IPs is not supported on Anyscale.
|
113
|
+
Use the Anyscale console to view cluster node information.
|
114
|
+
"""
|
115
|
+
raise click.ClickException("Listing IPs is not supported on Anyscale")
|
@@ -12,7 +12,11 @@ import anyscale
|
|
12
12
|
from anyscale.cli_logger import BlockLogger
|
13
13
|
from anyscale.commands import command_examples
|
14
14
|
from anyscale.commands.list_util import display_list
|
15
|
-
from anyscale.commands.util import
|
15
|
+
from anyscale.commands.util import (
|
16
|
+
AnyscaleCommand,
|
17
|
+
DeprecatedAnyscaleCommand,
|
18
|
+
NotRequiredIf,
|
19
|
+
)
|
16
20
|
from anyscale.controllers.project_controller import ProjectController
|
17
21
|
from anyscale.project.models import (
|
18
22
|
CreateProjectCollaborator,
|
@@ -441,6 +445,10 @@ def _default_project_name() -> str:
|
|
441
445
|
"[DEPRECATED] Create a new project or attach this directory to an existing project."
|
442
446
|
),
|
443
447
|
hidden=True,
|
448
|
+
cls=DeprecatedAnyscaleCommand,
|
449
|
+
removal_date="2025-10-01",
|
450
|
+
deprecation_message="`anyscale init` has been deprecated",
|
451
|
+
alternative="use `anyscale project create` to create a new project",
|
444
452
|
)
|
445
453
|
@click.option(
|
446
454
|
"--project-id",
|
@@ -474,10 +482,11 @@ def anyscale_init(
|
|
474
482
|
config: Optional[str],
|
475
483
|
requirements: Optional[str],
|
476
484
|
) -> None:
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
485
|
+
"""Create a new project or attach this directory to an existing project.
|
486
|
+
|
487
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
488
|
+
Use 'anyscale project create' to create a new project.
|
489
|
+
"""
|
481
490
|
if (project_id and name) or not (project_id or name):
|
482
491
|
raise click.BadArgumentUsage(
|
483
492
|
"Only one of project_id and name must be provided."
|
@@ -491,6 +500,10 @@ def anyscale_init(
|
|
491
500
|
name="init",
|
492
501
|
help="[DEPRECATED] Create a new project or attach this directory to an existing project.",
|
493
502
|
hidden=True,
|
503
|
+
cls=DeprecatedAnyscaleCommand,
|
504
|
+
removal_date="2025-10-01",
|
505
|
+
deprecation_message="`anyscale project init` has been deprecated",
|
506
|
+
alternative="use `anyscale project create` to create a new project and specify a project id or name for the other Anyscale CLI commands",
|
494
507
|
)
|
495
508
|
@click.option(
|
496
509
|
"--project-id",
|
@@ -510,11 +523,11 @@ def anyscale_init(
|
|
510
523
|
default=_default_project_name(),
|
511
524
|
)
|
512
525
|
def init(project_id: Optional[str], name: Optional[str],) -> None:
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
526
|
+
"""Create a new project or attach this directory to an existing project.
|
527
|
+
|
528
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
529
|
+
Use 'anyscale project create' to create a new project.
|
530
|
+
"""
|
518
531
|
if (project_id and name) or not (project_id or name):
|
519
532
|
raise click.BadArgumentUsage(
|
520
533
|
"Only one of --project-id and --name must be provided."
|
@@ -9,7 +9,10 @@ import yaml
|
|
9
9
|
import anyscale
|
10
10
|
from anyscale.cli_logger import BlockLogger
|
11
11
|
from anyscale.commands import command_examples
|
12
|
-
from anyscale.commands.util import
|
12
|
+
from anyscale.commands.util import (
|
13
|
+
AnyscaleCommand,
|
14
|
+
DeprecatedAnyscaleCommand,
|
15
|
+
)
|
13
16
|
from anyscale.controllers.schedule_controller import ScheduleController
|
14
17
|
from anyscale.schedule.models import JobConfig, ScheduleConfig, ScheduleState
|
15
18
|
|
@@ -94,9 +97,11 @@ def apply(config_file: str, name: Optional[str],) -> None:
|
|
94
97
|
|
95
98
|
@schedule_cli.command(
|
96
99
|
name="create",
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
+
help="[DEPRECATED - use 'apply' instead] Create a schedule.",
|
101
|
+
cls=DeprecatedAnyscaleCommand,
|
102
|
+
removal_date="2025-10-01",
|
103
|
+
deprecation_message="`anyscale schedule create` has been deprecated",
|
104
|
+
alternative="use `anyscale schedule apply` instead",
|
100
105
|
)
|
101
106
|
@click.argument("schedule_config_file", required=True)
|
102
107
|
@click.option(
|
@@ -108,13 +113,15 @@ def apply(config_file: str, name: Optional[str],) -> None:
|
|
108
113
|
def create(
|
109
114
|
schedule_config_file: str, name: Optional[str], description: Optional[str],
|
110
115
|
) -> None:
|
111
|
-
"""
|
116
|
+
"""Create or Update a Schedule.
|
117
|
+
|
118
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
119
|
+
Use 'anyscale schedule apply' instead.
|
112
120
|
|
113
121
|
This function accepts 1 argument, a path to a YAML config file that defines this schedule.
|
114
122
|
|
115
123
|
Note: if a schedule with the name exists in the specified project, it will be updated instead.
|
116
124
|
"""
|
117
|
-
log.warning("DEPRECATED: Use `anyscale schedule apply` instead.")
|
118
125
|
job_controller = ScheduleController()
|
119
126
|
job_controller.apply(
|
120
127
|
schedule_config_file, name, description,
|
@@ -123,9 +130,11 @@ def create(
|
|
123
130
|
|
124
131
|
@schedule_cli.command(
|
125
132
|
name="update",
|
126
|
-
|
127
|
-
|
128
|
-
|
133
|
+
help="[DEPRECATED - use 'apply' instead] Update a schedule.",
|
134
|
+
cls=DeprecatedAnyscaleCommand,
|
135
|
+
removal_date="2025-10-01",
|
136
|
+
deprecation_message="`anyscale schedule update` has been deprecated",
|
137
|
+
alternative="use `anyscale schedule apply` instead",
|
129
138
|
)
|
130
139
|
@click.argument("schedule_config_file", required=True)
|
131
140
|
@click.option(
|
@@ -137,11 +146,13 @@ def create(
|
|
137
146
|
def update(
|
138
147
|
schedule_config_file: str, name: Optional[str], description: Optional[str],
|
139
148
|
) -> None:
|
140
|
-
"""
|
149
|
+
"""Create or Update a Schedule.
|
150
|
+
|
151
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
152
|
+
Use 'anyscale schedule apply' instead.
|
141
153
|
|
142
154
|
This function accepts 1 argument, a path to a YAML config file that defines this schedule.
|
143
155
|
"""
|
144
|
-
log.warning("DEPRECATED: Use `anyscale schedule apply` instead.")
|
145
156
|
job_controller = ScheduleController()
|
146
157
|
job_controller.apply(
|
147
158
|
schedule_config_file, name, description,
|
@@ -22,7 +22,7 @@ from anyscale.commands.list_util import (
|
|
22
22
|
from anyscale.commands.util import (
|
23
23
|
AnyscaleCommand,
|
24
24
|
convert_kv_strings_to_dict,
|
25
|
-
|
25
|
+
DeprecatedAnyscaleCommand,
|
26
26
|
override_env_vars,
|
27
27
|
)
|
28
28
|
from anyscale.controllers.service_controller import ServiceController
|
@@ -565,10 +565,11 @@ def controller_logs(
|
|
565
565
|
|
566
566
|
@service_cli.command(
|
567
567
|
name="rollout",
|
568
|
-
help="Roll out a service.",
|
569
|
-
cls=
|
570
|
-
|
571
|
-
|
568
|
+
help="[DEPRECATED - use 'deploy' instead] Roll out a service.",
|
569
|
+
cls=DeprecatedAnyscaleCommand,
|
570
|
+
removal_date="2025-10-01",
|
571
|
+
deprecation_message="`anyscale service rollout` has been deprecated",
|
572
|
+
alternative="use `anyscale service deploy` instead",
|
572
573
|
)
|
573
574
|
@click.option(
|
574
575
|
"-f",
|
@@ -626,7 +627,11 @@ def rollout( # noqa: PLR0913
|
|
626
627
|
in_place: bool,
|
627
628
|
no_auto_complete_rollout: bool,
|
628
629
|
):
|
629
|
-
"""Start or update a service rollout to a new version.
|
630
|
+
"""Start or update a service rollout to a new version.
|
631
|
+
|
632
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
633
|
+
Use 'anyscale service deploy' instead.
|
634
|
+
"""
|
630
635
|
if in_place:
|
631
636
|
if rollout_strategy is not None:
|
632
637
|
raise click.ClickException(
|
anyscale/commands/util.py
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
from copy import deepcopy
|
2
|
-
from
|
2
|
+
from datetime import date, datetime
|
3
|
+
import sys
|
4
|
+
from typing import Dict, Optional, Tuple, TypeVar
|
3
5
|
|
4
6
|
import click
|
7
|
+
import colorama
|
5
8
|
|
6
9
|
from anyscale._private.workload import WorkloadConfig
|
10
|
+
from anyscale.cli_logger import BlockLogger
|
11
|
+
|
12
|
+
|
13
|
+
logger = BlockLogger()
|
7
14
|
|
8
15
|
|
9
16
|
class AnyscaleCommand(click.Command):
|
@@ -151,3 +158,89 @@ def override_env_vars(config: T, overrides: Dict[str, str]) -> T:
|
|
151
158
|
final_env_vars = deepcopy(config.env_vars) if config.env_vars else {}
|
152
159
|
final_env_vars.update(overrides)
|
153
160
|
return config.options(env_vars=final_env_vars)
|
161
|
+
|
162
|
+
|
163
|
+
class DeprecatedAnyscaleCommand(click.Command):
|
164
|
+
"""
|
165
|
+
DeprecatedAnyscaleCommand is a subclass of click.Command that shows deprecation warnings.
|
166
|
+
|
167
|
+
Similar to LegacyAnyscaleCommand but focuses on deprecation with dates and alternatives.
|
168
|
+
"""
|
169
|
+
|
170
|
+
def __init__(self, *args, **kwargs):
|
171
|
+
self.__removal_date__ = kwargs.pop("removal_date", None)
|
172
|
+
self.__deprecation_message__ = kwargs.pop("deprecation_message", None)
|
173
|
+
self.__alternative__ = kwargs.pop("alternative", None)
|
174
|
+
super().__init__(*args, **kwargs)
|
175
|
+
|
176
|
+
def get_help(self, ctx):
|
177
|
+
"""Override get_help to show deprecation warning when help is displayed."""
|
178
|
+
self._show_deprecation_warning()
|
179
|
+
return super().get_help(ctx)
|
180
|
+
|
181
|
+
def invoke(self, ctx):
|
182
|
+
"""Override invoke to show deprecation warning before executing."""
|
183
|
+
self._show_deprecation_warning()
|
184
|
+
return super().invoke(ctx)
|
185
|
+
|
186
|
+
def _show_deprecation_warning(self):
|
187
|
+
"""Show the deprecation warning."""
|
188
|
+
|
189
|
+
# Visual separator for attention
|
190
|
+
print("\n" + "=" * 80, file=sys.stderr)
|
191
|
+
print(
|
192
|
+
f"{colorama.Style.BRIGHT}{colorama.Fore.YELLOW}⚠️ DEPRECATION WARNING ⚠️{colorama.Style.RESET_ALL}",
|
193
|
+
file=sys.stderr,
|
194
|
+
)
|
195
|
+
print("=" * 80, file=sys.stderr)
|
196
|
+
|
197
|
+
# Build deprecation message
|
198
|
+
base_msg = (
|
199
|
+
self.__deprecation_message__
|
200
|
+
if self.__deprecation_message__
|
201
|
+
else f"Command '{self.name}' is deprecated"
|
202
|
+
)
|
203
|
+
|
204
|
+
# Removal date information with grammar-aware connector
|
205
|
+
date_msg = None
|
206
|
+
if self.__removal_date__:
|
207
|
+
date_str = self._format_removal_date(self.__removal_date__)
|
208
|
+
if date_str:
|
209
|
+
ends_with_punct = base_msg.strip().endswith((".", "!", "?"))
|
210
|
+
if ends_with_punct:
|
211
|
+
date_msg = f"It will be removed on {date_str}"
|
212
|
+
else:
|
213
|
+
date_msg = f"and will be removed on {date_str}"
|
214
|
+
|
215
|
+
# Alternative suggestion
|
216
|
+
alternative_msg = None
|
217
|
+
if self.__alternative__:
|
218
|
+
alternative_msg = f"\n\n➡️ {colorama.Style.BRIGHT}Please {self.__alternative__}{colorama.Style.RESET_ALL}"
|
219
|
+
|
220
|
+
main_line_parts = [part for part in (base_msg, date_msg) if part]
|
221
|
+
deprecation_msg = " ".join(main_line_parts)
|
222
|
+
if alternative_msg:
|
223
|
+
deprecation_msg += alternative_msg
|
224
|
+
|
225
|
+
# Logger warning but also print directly for visibility
|
226
|
+
print(
|
227
|
+
f"\n{colorama.Fore.YELLOW}{deprecation_msg}{colorama.Style.RESET_ALL}",
|
228
|
+
file=sys.stderr,
|
229
|
+
)
|
230
|
+
print("=" * 80 + "\n", file=sys.stderr)
|
231
|
+
|
232
|
+
def _format_removal_date(self, removal_date) -> Optional[str]:
|
233
|
+
"""Format the removal date for display."""
|
234
|
+
try:
|
235
|
+
if isinstance(removal_date, str):
|
236
|
+
parsed_date = datetime.strptime(removal_date, "%Y-%m-%d").date()
|
237
|
+
elif isinstance(removal_date, datetime):
|
238
|
+
parsed_date = removal_date.date()
|
239
|
+
elif isinstance(removal_date, date):
|
240
|
+
parsed_date = removal_date
|
241
|
+
else:
|
242
|
+
return None
|
243
|
+
|
244
|
+
return parsed_date.strftime("%Y-%m-%d")
|
245
|
+
except (ValueError, AttributeError):
|
246
|
+
return str(removal_date)
|