anyscale 0.26.69__py3-none-any.whl → 0.26.70__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 +67 -1
- anyscale/_private/anyscale_client/common.py +20 -1
- anyscale/_private/anyscale_client/fake_anyscale_client.py +77 -10
- anyscale/client/README.md +14 -4
- anyscale/client/openapi_client/__init__.py +11 -4
- anyscale/client/openapi_client/api/default_api.py +462 -23
- anyscale/client/openapi_client/models/__init__.py +11 -4
- anyscale/client/openapi_client/models/api_key_info.py +29 -3
- anyscale/client/openapi_client/models/apply_autoscaling_config_update_model.py +350 -0
- anyscale/client/openapi_client/models/apply_production_service_multi_version_v2_model.py +207 -0
- anyscale/client/openapi_client/models/apply_production_service_v2_model.py +31 -3
- anyscale/client/openapi_client/models/baseimagesenum.py +70 -1
- anyscale/client/openapi_client/models/cloud_data_bucket_file_type.py +2 -1
- anyscale/client/openapi_client/models/{oauthconnectionresponse_response.py → clouddeployment_response.py} +11 -11
- anyscale/client/openapi_client/models/create_experimental_workspace.py +29 -1
- anyscale/client/openapi_client/models/create_workspace_from_template.py +29 -1
- anyscale/client/openapi_client/models/create_workspace_template_version.py +31 -3
- anyscale/client/openapi_client/models/decorated_list_service_api_model.py +58 -1
- anyscale/client/openapi_client/models/decorated_production_service_v2_api_model.py +60 -3
- anyscale/client/openapi_client/models/decorated_service_event_api_model.py +3 -3
- anyscale/client/openapi_client/models/describe_machine_pool_machines_filters.py +33 -5
- anyscale/client/openapi_client/models/describe_machine_pool_workloads_filters.py +33 -5
- anyscale/client/openapi_client/models/{service_event_level.py → entity_type.py} +9 -9
- anyscale/client/openapi_client/models/event_level.py +2 -1
- anyscale/client/openapi_client/models/job_event_fields.py +206 -0
- anyscale/client/openapi_client/models/machine_type_partition_filter.py +152 -0
- anyscale/client/openapi_client/models/partition_info.py +30 -1
- anyscale/client/openapi_client/models/production_job_event.py +3 -3
- anyscale/client/openapi_client/models/rollout_strategy.py +2 -1
- anyscale/client/openapi_client/models/service_event_fields.py +318 -0
- anyscale/client/openapi_client/models/supportedbaseimagesenum.py +70 -1
- anyscale/client/openapi_client/models/task_summary_config.py +29 -3
- anyscale/client/openapi_client/models/task_table_config.py +29 -3
- anyscale/client/openapi_client/models/unified_event.py +377 -0
- anyscale/client/openapi_client/models/{ha_job_event_level.py → unified_origin_filter.py} +21 -9
- anyscale/client/openapi_client/models/unifiedevent_list_response.py +147 -0
- anyscale/client/openapi_client/models/workspace_event_fields.py +122 -0
- anyscale/client/openapi_client/models/workspace_template_version.py +30 -1
- anyscale/client/openapi_client/models/workspace_template_version_data_object.py +30 -1
- anyscale/cloud/models.py +2 -2
- anyscale/commands/cloud_commands.py +133 -2
- anyscale/commands/job_commands.py +1 -1
- anyscale/commands/service_commands.py +130 -67
- anyscale/commands/setup_k8s.py +546 -31
- anyscale/controllers/cloud_controller.py +15 -2
- anyscale/controllers/kubernetes_verifier.py +80 -66
- anyscale/job/_private/job_sdk.py +47 -1
- anyscale/job/commands.py +3 -0
- anyscale/sdk/anyscale_client/models/apply_production_service_v2_model.py +31 -3
- anyscale/sdk/anyscale_client/models/apply_service_model.py +31 -3
- anyscale/sdk/anyscale_client/models/baseimagesenum.py +70 -1
- anyscale/sdk/anyscale_client/models/rollout_strategy.py +2 -1
- anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +70 -1
- anyscale/service/__init__.py +11 -3
- anyscale/service/_private/service_sdk.py +361 -35
- anyscale/service/commands.py +15 -3
- anyscale/service/models.py +12 -0
- anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
- anyscale/version.py +1 -1
- {anyscale-0.26.69.dist-info → anyscale-0.26.70.dist-info}/METADATA +1 -1
- {anyscale-0.26.69.dist-info → anyscale-0.26.70.dist-info}/RECORD +66 -59
- anyscale/client/openapi_client/models/o_auth_connection_response.py +0 -229
- {anyscale-0.26.69.dist-info → anyscale-0.26.70.dist-info}/WHEEL +0 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.70.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.70.dist-info}/licenses/LICENSE +0 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.70.dist-info}/licenses/NOTICE +0 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.70.dist-info}/top_level.txt +0 -0
|
@@ -40,6 +40,7 @@ class WorkspaceTemplateVersion(object):
|
|
|
40
40
|
'id': 'str',
|
|
41
41
|
'version': 'int',
|
|
42
42
|
'creator_id': 'str',
|
|
43
|
+
'creator_email': 'str',
|
|
43
44
|
'created_at': 'datetime'
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -51,10 +52,11 @@ class WorkspaceTemplateVersion(object):
|
|
|
51
52
|
'id': 'id',
|
|
52
53
|
'version': 'version',
|
|
53
54
|
'creator_id': 'creator_id',
|
|
55
|
+
'creator_email': 'creator_email',
|
|
54
56
|
'created_at': 'created_at'
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
def __init__(self, template_id=None, image_uri=None, compute_configs=None, artifacts=None, id=None, version=None, creator_id=None, created_at=None, local_vars_configuration=None): # noqa: E501
|
|
59
|
+
def __init__(self, template_id=None, image_uri=None, compute_configs=None, artifacts=None, id=None, version=None, creator_id=None, creator_email=None, created_at=None, local_vars_configuration=None): # noqa: E501
|
|
58
60
|
"""WorkspaceTemplateVersion - a model defined in OpenAPI""" # noqa: E501
|
|
59
61
|
if local_vars_configuration is None:
|
|
60
62
|
local_vars_configuration = Configuration()
|
|
@@ -67,6 +69,7 @@ class WorkspaceTemplateVersion(object):
|
|
|
67
69
|
self._id = None
|
|
68
70
|
self._version = None
|
|
69
71
|
self._creator_id = None
|
|
72
|
+
self._creator_email = None
|
|
70
73
|
self._created_at = None
|
|
71
74
|
self.discriminator = None
|
|
72
75
|
|
|
@@ -80,6 +83,7 @@ class WorkspaceTemplateVersion(object):
|
|
|
80
83
|
self.id = id
|
|
81
84
|
self.version = version
|
|
82
85
|
self.creator_id = creator_id
|
|
86
|
+
self.creator_email = creator_email
|
|
83
87
|
self.created_at = created_at
|
|
84
88
|
|
|
85
89
|
@property
|
|
@@ -251,6 +255,31 @@ class WorkspaceTemplateVersion(object):
|
|
|
251
255
|
|
|
252
256
|
self._creator_id = creator_id
|
|
253
257
|
|
|
258
|
+
@property
|
|
259
|
+
def creator_email(self):
|
|
260
|
+
"""Gets the creator_email of this WorkspaceTemplateVersion. # noqa: E501
|
|
261
|
+
|
|
262
|
+
Email of the creator # noqa: E501
|
|
263
|
+
|
|
264
|
+
:return: The creator_email of this WorkspaceTemplateVersion. # noqa: E501
|
|
265
|
+
:rtype: str
|
|
266
|
+
"""
|
|
267
|
+
return self._creator_email
|
|
268
|
+
|
|
269
|
+
@creator_email.setter
|
|
270
|
+
def creator_email(self, creator_email):
|
|
271
|
+
"""Sets the creator_email of this WorkspaceTemplateVersion.
|
|
272
|
+
|
|
273
|
+
Email of the creator # noqa: E501
|
|
274
|
+
|
|
275
|
+
:param creator_email: The creator_email of this WorkspaceTemplateVersion. # noqa: E501
|
|
276
|
+
:type: str
|
|
277
|
+
"""
|
|
278
|
+
if self.local_vars_configuration.client_side_validation and creator_email is None: # noqa: E501
|
|
279
|
+
raise ValueError("Invalid value for `creator_email`, must not be `None`") # noqa: E501
|
|
280
|
+
|
|
281
|
+
self._creator_email = creator_email
|
|
282
|
+
|
|
254
283
|
@property
|
|
255
284
|
def created_at(self):
|
|
256
285
|
"""Gets the created_at of this WorkspaceTemplateVersion. # noqa: E501
|
|
@@ -40,6 +40,7 @@ class WorkspaceTemplateVersionDataObject(object):
|
|
|
40
40
|
'id': 'str',
|
|
41
41
|
'version': 'int',
|
|
42
42
|
'creator_id': 'str',
|
|
43
|
+
'creator_email': 'str',
|
|
43
44
|
'created_at': 'datetime'
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -51,10 +52,11 @@ class WorkspaceTemplateVersionDataObject(object):
|
|
|
51
52
|
'id': 'id',
|
|
52
53
|
'version': 'version',
|
|
53
54
|
'creator_id': 'creator_id',
|
|
55
|
+
'creator_email': 'creator_email',
|
|
54
56
|
'created_at': 'created_at'
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
def __init__(self, template_id=None, image_uri=None, compute_configs=None, artifacts=None, id=None, version=None, creator_id=None, created_at=None, local_vars_configuration=None): # noqa: E501
|
|
59
|
+
def __init__(self, template_id=None, image_uri=None, compute_configs=None, artifacts=None, id=None, version=None, creator_id=None, creator_email=None, created_at=None, local_vars_configuration=None): # noqa: E501
|
|
58
60
|
"""WorkspaceTemplateVersionDataObject - a model defined in OpenAPI""" # noqa: E501
|
|
59
61
|
if local_vars_configuration is None:
|
|
60
62
|
local_vars_configuration = Configuration()
|
|
@@ -67,6 +69,7 @@ class WorkspaceTemplateVersionDataObject(object):
|
|
|
67
69
|
self._id = None
|
|
68
70
|
self._version = None
|
|
69
71
|
self._creator_id = None
|
|
72
|
+
self._creator_email = None
|
|
70
73
|
self._created_at = None
|
|
71
74
|
self.discriminator = None
|
|
72
75
|
|
|
@@ -80,6 +83,7 @@ class WorkspaceTemplateVersionDataObject(object):
|
|
|
80
83
|
self.id = id
|
|
81
84
|
self.version = version
|
|
82
85
|
self.creator_id = creator_id
|
|
86
|
+
self.creator_email = creator_email
|
|
83
87
|
self.created_at = created_at
|
|
84
88
|
|
|
85
89
|
@property
|
|
@@ -251,6 +255,31 @@ class WorkspaceTemplateVersionDataObject(object):
|
|
|
251
255
|
|
|
252
256
|
self._creator_id = creator_id
|
|
253
257
|
|
|
258
|
+
@property
|
|
259
|
+
def creator_email(self):
|
|
260
|
+
"""Gets the creator_email of this WorkspaceTemplateVersionDataObject. # noqa: E501
|
|
261
|
+
|
|
262
|
+
Email of the creator # noqa: E501
|
|
263
|
+
|
|
264
|
+
:return: The creator_email of this WorkspaceTemplateVersionDataObject. # noqa: E501
|
|
265
|
+
:rtype: str
|
|
266
|
+
"""
|
|
267
|
+
return self._creator_email
|
|
268
|
+
|
|
269
|
+
@creator_email.setter
|
|
270
|
+
def creator_email(self, creator_email):
|
|
271
|
+
"""Sets the creator_email of this WorkspaceTemplateVersionDataObject.
|
|
272
|
+
|
|
273
|
+
Email of the creator # noqa: E501
|
|
274
|
+
|
|
275
|
+
:param creator_email: The creator_email of this WorkspaceTemplateVersionDataObject. # noqa: E501
|
|
276
|
+
:type: str
|
|
277
|
+
"""
|
|
278
|
+
if self.local_vars_configuration.client_side_validation and creator_email is None: # noqa: E501
|
|
279
|
+
raise ValueError("Invalid value for `creator_email`, must not be `None`") # noqa: E501
|
|
280
|
+
|
|
281
|
+
self._creator_email = creator_email
|
|
282
|
+
|
|
254
283
|
@property
|
|
255
284
|
def created_at(self):
|
|
256
285
|
"""Gets the created_at of this WorkspaceTemplateVersionDataObject. # noqa: E501
|
anyscale/cloud/models.py
CHANGED
|
@@ -497,9 +497,9 @@ compute_stack: VM
|
|
|
497
497
|
region: us-west-2
|
|
498
498
|
networking_mode: PUBLIC
|
|
499
499
|
object_storage:
|
|
500
|
-
bucket_name: s3://my-bucket
|
|
500
|
+
bucket_name: s3://my-bucket
|
|
501
501
|
file_storage:
|
|
502
|
-
file_storage_id: fs-12345678901234567
|
|
502
|
+
file_storage_id: fs-12345678901234567
|
|
503
503
|
aws_config:
|
|
504
504
|
vpc_id: vpc-12345678901234567
|
|
505
505
|
subnet_ids:
|
|
@@ -23,7 +23,10 @@ from anyscale.client.openapi_client.models import (
|
|
|
23
23
|
from anyscale.client.openapi_client.models.compute_stack import ComputeStack
|
|
24
24
|
from anyscale.cloud.models import CreateCloudCollaborator, CreateCloudCollaborators
|
|
25
25
|
from anyscale.commands import command_examples
|
|
26
|
-
from anyscale.commands.setup_k8s import
|
|
26
|
+
from anyscale.commands.setup_k8s import (
|
|
27
|
+
setup_kubernetes_cloud,
|
|
28
|
+
setup_kubernetes_cloud_resource,
|
|
29
|
+
)
|
|
27
30
|
from anyscale.commands.util import AnyscaleCommand, OptionPromptNull
|
|
28
31
|
from anyscale.controllers.cloud_controller import CloudController
|
|
29
32
|
from anyscale.util import (
|
|
@@ -381,6 +384,134 @@ def cloud_resource_create(
|
|
|
381
384
|
print(e)
|
|
382
385
|
|
|
383
386
|
|
|
387
|
+
@cloud_resource_group.command(
|
|
388
|
+
name="setup",
|
|
389
|
+
help="Set up cloud resources for an existing cloud on a Kubernetes cluster.",
|
|
390
|
+
cls=AnyscaleCommand,
|
|
391
|
+
is_alpha=True,
|
|
392
|
+
)
|
|
393
|
+
@click.option(
|
|
394
|
+
"--provider",
|
|
395
|
+
help="The cloud provider type.",
|
|
396
|
+
required=True,
|
|
397
|
+
type=click.Choice(["aws", "gcp"], case_sensitive=False),
|
|
398
|
+
)
|
|
399
|
+
@click.option(
|
|
400
|
+
"--region", help="Region to set up the resources in.", required=True,
|
|
401
|
+
)
|
|
402
|
+
@click.option(
|
|
403
|
+
"--stack",
|
|
404
|
+
help="The compute stack to use (only k8s is supported for this command).",
|
|
405
|
+
required=False,
|
|
406
|
+
type=click.Choice(["k8s"], case_sensitive=False),
|
|
407
|
+
default="k8s",
|
|
408
|
+
show_default=True,
|
|
409
|
+
)
|
|
410
|
+
@click.option(
|
|
411
|
+
"--cloud",
|
|
412
|
+
help="The name of the existing cloud to add resources to. Either this or --cloud-id is required.",
|
|
413
|
+
type=str,
|
|
414
|
+
required=False,
|
|
415
|
+
)
|
|
416
|
+
@click.option(
|
|
417
|
+
"--cloud-id",
|
|
418
|
+
help="The ID of the existing cloud to add resources to. Either this or --cloud is required.",
|
|
419
|
+
type=str,
|
|
420
|
+
required=False,
|
|
421
|
+
)
|
|
422
|
+
@click.option(
|
|
423
|
+
"--cluster-name", help="Kubernetes cluster name.", required=True, type=str,
|
|
424
|
+
)
|
|
425
|
+
@click.option(
|
|
426
|
+
"--namespace",
|
|
427
|
+
help="Kubernetes namespace for Anyscale operator.",
|
|
428
|
+
required=False,
|
|
429
|
+
type=str,
|
|
430
|
+
default="anyscale-operator",
|
|
431
|
+
)
|
|
432
|
+
@click.option(
|
|
433
|
+
"--project-id",
|
|
434
|
+
help="Globally Unique project ID for GCP clouds (e.g., my-project-abc123)",
|
|
435
|
+
required=False,
|
|
436
|
+
type=str,
|
|
437
|
+
)
|
|
438
|
+
@click.option(
|
|
439
|
+
"--functional-verify",
|
|
440
|
+
help="Verify the cloud is functional. This will check that the cloud can launch workspace/service.",
|
|
441
|
+
required=False,
|
|
442
|
+
is_flag=False,
|
|
443
|
+
flag_value="workspace",
|
|
444
|
+
)
|
|
445
|
+
@click.option(
|
|
446
|
+
"--yes", "-y", is_flag=True, default=False, help="Skip asking for confirmation."
|
|
447
|
+
)
|
|
448
|
+
@click.option(
|
|
449
|
+
"--values-file",
|
|
450
|
+
help="Path to save the generated Helm values file (default: auto-generated with timestamp).",
|
|
451
|
+
required=False,
|
|
452
|
+
type=str,
|
|
453
|
+
)
|
|
454
|
+
@click.option(
|
|
455
|
+
"--debug", is_flag=True, default=False, help="Enable debug logging.",
|
|
456
|
+
)
|
|
457
|
+
@click.option(
|
|
458
|
+
"--operator-chart",
|
|
459
|
+
help="Path to operator chart (skips helm repo add/update).",
|
|
460
|
+
required=False,
|
|
461
|
+
type=str,
|
|
462
|
+
hidden=True,
|
|
463
|
+
)
|
|
464
|
+
@click.option(
|
|
465
|
+
"--resource-name",
|
|
466
|
+
help="Name for the cloud resource (optional, will be auto-generated if not provided)",
|
|
467
|
+
required=False,
|
|
468
|
+
type=str,
|
|
469
|
+
default=None,
|
|
470
|
+
)
|
|
471
|
+
def cloud_resource_setup( # noqa: PLR0913
|
|
472
|
+
provider: str,
|
|
473
|
+
region: str,
|
|
474
|
+
stack: str,
|
|
475
|
+
cloud: Optional[str],
|
|
476
|
+
cloud_id: Optional[str],
|
|
477
|
+
cluster_name: str,
|
|
478
|
+
namespace: str,
|
|
479
|
+
project_id: Optional[str],
|
|
480
|
+
functional_verify: Optional[str],
|
|
481
|
+
yes: bool,
|
|
482
|
+
values_file: Optional[str],
|
|
483
|
+
debug: bool,
|
|
484
|
+
operator_chart: Optional[str],
|
|
485
|
+
resource_name: Optional[str],
|
|
486
|
+
) -> None:
|
|
487
|
+
"""
|
|
488
|
+
Set up cloud resources for an existing Anyscale cloud on a Kubernetes cluster.
|
|
489
|
+
|
|
490
|
+
This command sets up infrastructure (S3/GCS buckets, IAM roles, etc.) and installs
|
|
491
|
+
the Anyscale operator on your Kubernetes cluster, then creates a cloud resource in
|
|
492
|
+
an existing cloud instead of registering a new cloud.
|
|
493
|
+
"""
|
|
494
|
+
# Validate stack
|
|
495
|
+
if stack != "k8s":
|
|
496
|
+
raise click.ClickException("Only --stack=k8s is supported for this command.")
|
|
497
|
+
|
|
498
|
+
setup_kubernetes_cloud_resource(
|
|
499
|
+
provider=provider,
|
|
500
|
+
region=region,
|
|
501
|
+
cloud_name=cloud,
|
|
502
|
+
cloud_id=cloud_id,
|
|
503
|
+
cluster_name=cluster_name,
|
|
504
|
+
namespace=namespace,
|
|
505
|
+
project_id=project_id,
|
|
506
|
+
functional_verify=bool(functional_verify),
|
|
507
|
+
yes=yes,
|
|
508
|
+
values_file=values_file,
|
|
509
|
+
debug=debug,
|
|
510
|
+
operator_chart=operator_chart,
|
|
511
|
+
resource_name=resource_name,
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
|
|
384
515
|
@cloud_resource_group.command(
|
|
385
516
|
name="delete",
|
|
386
517
|
help="Remove a cloud resource from an existing cloud.",
|
|
@@ -451,7 +582,7 @@ def cloud_resource_delete(cloud: str, resource: str, yes: bool,) -> None:
|
|
|
451
582
|
@click.option(
|
|
452
583
|
"--resources-file",
|
|
453
584
|
"-f",
|
|
454
|
-
help="EXPERIMENTAL: Path to a YAML file defining a list of cloud resources. Schema: https://docs.anyscale.com/reference/cloud/#cloudresource.",
|
|
585
|
+
help="EXPERIMENTAL: Path to a YAML file defining a single cloud resource or a list of cloud resources. Schema: https://docs.anyscale.com/reference/cloud/#cloudresource.",
|
|
455
586
|
required=False,
|
|
456
587
|
)
|
|
457
588
|
@click.option(
|
|
@@ -347,7 +347,7 @@ and override the entrypoint with `python main.py`.
|
|
|
347
347
|
log.info("Use `--wait` to wait for the job to run and stream logs.")
|
|
348
348
|
|
|
349
349
|
if wait:
|
|
350
|
-
anyscale.job.wait(id=job_id)
|
|
350
|
+
anyscale.job.wait(id=job_id, follow=True)
|
|
351
351
|
|
|
352
352
|
|
|
353
353
|
# TODO(mowen): Add cloud support for this when we refactor to new SDK method
|
|
@@ -79,8 +79,9 @@ def _read_name_from_config_file(path: str):
|
|
|
79
79
|
"-f",
|
|
80
80
|
"--config-file",
|
|
81
81
|
required=False,
|
|
82
|
-
default=
|
|
82
|
+
default=[],
|
|
83
83
|
type=str,
|
|
84
|
+
multiple=True,
|
|
84
85
|
help="Path to a YAML config file to deploy. When deploying from a file, import path and arguments cannot be provided. Command-line flags will overwrite values read from the file.",
|
|
85
86
|
)
|
|
86
87
|
@click.option(
|
|
@@ -202,8 +203,15 @@ def _read_name_from_config_file(path: str):
|
|
|
202
203
|
type=str,
|
|
203
204
|
help="Named project to use for the service. If not provided, the default project for the cloud will be used (or, if running in a workspace, the project of the workspace).",
|
|
204
205
|
)
|
|
206
|
+
@click.option(
|
|
207
|
+
"--versions",
|
|
208
|
+
required=False,
|
|
209
|
+
default=None,
|
|
210
|
+
type=str,
|
|
211
|
+
help="Defines the traffic and capacity percents per version. Capacity defaults to traffic.",
|
|
212
|
+
)
|
|
205
213
|
def deploy( # noqa: PLR0912, PLR0913 C901
|
|
206
|
-
config_file:
|
|
214
|
+
config_file: List[str],
|
|
207
215
|
import_path: Optional[str],
|
|
208
216
|
arguments: Tuple[str],
|
|
209
217
|
name: Optional[str],
|
|
@@ -222,6 +230,7 @@ def deploy( # noqa: PLR0912, PLR0913 C901
|
|
|
222
230
|
py_module: Tuple[str],
|
|
223
231
|
cloud: Optional[str],
|
|
224
232
|
project: Optional[str],
|
|
233
|
+
versions: Optional[str],
|
|
225
234
|
):
|
|
226
235
|
"""Deploy or update a service.
|
|
227
236
|
|
|
@@ -238,102 +247,156 @@ def deploy( # noqa: PLR0912, PLR0913 C901
|
|
|
238
247
|
Command-line flags override values in the config file.
|
|
239
248
|
"""
|
|
240
249
|
|
|
241
|
-
if
|
|
242
|
-
if
|
|
250
|
+
if versions is None:
|
|
251
|
+
if len(config_file) == 1:
|
|
252
|
+
if import_path is not None or len(arguments) > 0:
|
|
253
|
+
raise click.ClickException(
|
|
254
|
+
"When a config file is provided, import path and application arguments can't be."
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
if not pathlib.Path(config_file[0]).is_file():
|
|
258
|
+
raise click.ClickException(f"Config file '{config_file[0]}' not found.")
|
|
259
|
+
|
|
260
|
+
config = ServiceConfig.from_yaml(config_file[0])
|
|
261
|
+
elif len(config_file) > 1:
|
|
243
262
|
raise click.ClickException(
|
|
244
|
-
"
|
|
263
|
+
"Multiple config files can be provided only when deploying multiple versions with --versions."
|
|
245
264
|
)
|
|
265
|
+
else:
|
|
266
|
+
# when config_file is not provided.
|
|
267
|
+
if import_path is None:
|
|
268
|
+
raise click.ClickException(
|
|
269
|
+
"Either config file or import path must be provided."
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
if (
|
|
273
|
+
import_path.endswith((".yaml", ".yml"))
|
|
274
|
+
or pathlib.Path(import_path).is_file()
|
|
275
|
+
):
|
|
276
|
+
log.warning(
|
|
277
|
+
f"The provided import path '{import_path}' looks like a config file. Did you mean to use '-f config.yaml'?"
|
|
278
|
+
)
|
|
246
279
|
|
|
247
|
-
|
|
248
|
-
|
|
280
|
+
app: Dict[str, Any] = {"import_path": import_path}
|
|
281
|
+
arguments_dict = convert_kv_strings_to_dict(arguments)
|
|
282
|
+
if arguments_dict:
|
|
283
|
+
app["args"] = arguments_dict
|
|
249
284
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if
|
|
285
|
+
config = ServiceConfig(applications=[app])
|
|
286
|
+
|
|
287
|
+
if containerfile and image_uri:
|
|
288
|
+
raise click.ClickException(
|
|
289
|
+
"Only one of '--containerfile' and '--image-uri' can be provided."
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
if ray_version and (not image_uri and not containerfile):
|
|
253
293
|
raise click.ClickException(
|
|
254
|
-
"
|
|
294
|
+
"Ray version can only be used with an image or containerfile.",
|
|
255
295
|
)
|
|
256
296
|
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
or pathlib.Path(import_path).is_file()
|
|
297
|
+
if registry_login_secret and (
|
|
298
|
+
not image_uri or ImageURI.from_str(image_uri).is_cluster_env_image()
|
|
260
299
|
):
|
|
261
|
-
|
|
262
|
-
|
|
300
|
+
raise click.ClickException(
|
|
301
|
+
"Registry login secret can only be used with an image that is not hosted on Anyscale."
|
|
263
302
|
)
|
|
264
303
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if arguments_dict:
|
|
268
|
-
app["args"] = arguments_dict
|
|
304
|
+
if name is not None:
|
|
305
|
+
config = config.options(name=name)
|
|
269
306
|
|
|
270
|
-
|
|
307
|
+
if image_uri is not None:
|
|
308
|
+
config = config.options(image_uri=image_uri)
|
|
271
309
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
"Only one of '--containerfile' and '--image-uri' can be provided."
|
|
275
|
-
)
|
|
310
|
+
if registry_login_secret is not None:
|
|
311
|
+
config = config.options(registry_login_secret=registry_login_secret)
|
|
276
312
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
"Ray version can only be used with an image or containerfile.",
|
|
280
|
-
)
|
|
313
|
+
if ray_version is not None:
|
|
314
|
+
config = config.options(ray_version=ray_version)
|
|
281
315
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
):
|
|
285
|
-
raise click.ClickException(
|
|
286
|
-
"Registry login secret can only be used with an image that is not hosted on Anyscale."
|
|
287
|
-
)
|
|
316
|
+
if containerfile is not None:
|
|
317
|
+
config = config.options(containerfile=containerfile)
|
|
288
318
|
|
|
289
|
-
|
|
290
|
-
|
|
319
|
+
if compute_config is not None:
|
|
320
|
+
config = config.options(compute_config=compute_config)
|
|
291
321
|
|
|
292
|
-
|
|
293
|
-
|
|
322
|
+
if working_dir is not None:
|
|
323
|
+
config = config.options(working_dir=working_dir)
|
|
294
324
|
|
|
295
|
-
|
|
296
|
-
|
|
325
|
+
if exclude:
|
|
326
|
+
config = config.options(excludes=[e for e in exclude])
|
|
297
327
|
|
|
298
|
-
|
|
299
|
-
|
|
328
|
+
if requirements is not None:
|
|
329
|
+
config = config.options(requirements=requirements)
|
|
300
330
|
|
|
301
|
-
|
|
302
|
-
|
|
331
|
+
if env:
|
|
332
|
+
config = override_env_vars(config, convert_kv_strings_to_dict(env))
|
|
303
333
|
|
|
304
|
-
|
|
305
|
-
|
|
334
|
+
if py_module:
|
|
335
|
+
for module in py_module:
|
|
336
|
+
if not pathlib.Path(module).is_dir():
|
|
337
|
+
raise click.ClickException(
|
|
338
|
+
f"Python module path '{module}' does not exist or is not a directory."
|
|
339
|
+
)
|
|
340
|
+
config = config.options(py_modules=[*py_module])
|
|
306
341
|
|
|
307
|
-
|
|
308
|
-
|
|
342
|
+
if cloud is not None:
|
|
343
|
+
config = config.options(cloud=cloud)
|
|
344
|
+
if project is not None:
|
|
345
|
+
config = config.options(project=project)
|
|
309
346
|
|
|
310
|
-
|
|
311
|
-
|
|
347
|
+
configs = config
|
|
348
|
+
else:
|
|
349
|
+
# When multiple versions are being deployed.
|
|
350
|
+
configs = [ServiceConfig.from_yaml(config) for config in config_file]
|
|
351
|
+
for config in configs:
|
|
352
|
+
if name is not None:
|
|
353
|
+
config = config.options(name=name)
|
|
312
354
|
|
|
313
|
-
|
|
314
|
-
|
|
355
|
+
if cloud is not None:
|
|
356
|
+
config = config.options(cloud=cloud)
|
|
315
357
|
|
|
316
|
-
|
|
317
|
-
|
|
358
|
+
if project is not None:
|
|
359
|
+
config = config.options(project=project)
|
|
318
360
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
361
|
+
if image_uri is not None:
|
|
362
|
+
log.warning("--image-uri is ignored.")
|
|
363
|
+
|
|
364
|
+
if registry_login_secret is not None:
|
|
365
|
+
log.warning("--registry-login-secret is ignored.")
|
|
366
|
+
|
|
367
|
+
if ray_version is not None:
|
|
368
|
+
log.warning("--ray-version is ignored.")
|
|
369
|
+
|
|
370
|
+
if containerfile is not None:
|
|
371
|
+
log.warning("--containerfile is ignored.")
|
|
372
|
+
|
|
373
|
+
if compute_config is not None:
|
|
374
|
+
log.warning("--compute-config is ignored.")
|
|
326
375
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
376
|
+
if working_dir is not None:
|
|
377
|
+
log.warning("--working-dir is ignored.")
|
|
378
|
+
|
|
379
|
+
if exclude:
|
|
380
|
+
log.warning("--exclude is ignored.")
|
|
381
|
+
|
|
382
|
+
if requirements is not None:
|
|
383
|
+
log.warning("--requirements is ignored.")
|
|
384
|
+
|
|
385
|
+
if env:
|
|
386
|
+
log.warning("--env is ignored.")
|
|
387
|
+
|
|
388
|
+
if py_module:
|
|
389
|
+
log.warning("--py-module is ignored.")
|
|
331
390
|
|
|
332
391
|
anyscale.service.deploy(
|
|
333
|
-
|
|
392
|
+
configs,
|
|
334
393
|
in_place=in_place,
|
|
335
394
|
canary_percent=canary_percent,
|
|
336
395
|
max_surge_percent=max_surge_percent,
|
|
396
|
+
versions=versions,
|
|
397
|
+
name=name,
|
|
398
|
+
cloud=cloud,
|
|
399
|
+
project=project,
|
|
337
400
|
)
|
|
338
401
|
|
|
339
402
|
|