anyscale 0.26.13__py3-none-any.whl → 0.26.15__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/fake_anyscale_client.py +1 -1
- anyscale/_private/docgen/models.md +2 -2
- anyscale/_private/models/model_base.py +5 -2
- anyscale/_private/utils/progress_util.py +2 -2
- anyscale/_private/workload/workload_sdk.py +4 -3
- anyscale/anyscale-cloud-setup.yaml +4 -0
- anyscale/client/README.md +20 -2
- anyscale/client/openapi_client/__init__.py +14 -1
- anyscale/client/openapi_client/api/default_api.py +847 -241
- anyscale/client/openapi_client/models/__init__.py +14 -1
- anyscale/client/openapi_client/models/baseimagesenum.py +2 -4
- anyscale/client/openapi_client/models/supportedbaseimagesenum.py +2 -2
- anyscale/client/openapi_client/models/task_exception_group_aggregate.py +175 -0
- anyscale/client/openapi_client/models/task_exception_group_aggregate_response.py +174 -0
- anyscale/client/openapi_client/models/task_function_name_group_aggregate.py +202 -0
- anyscale/client/openapi_client/models/task_function_name_group_aggregate_response.py +174 -0
- anyscale/client/openapi_client/models/task_grouped_aggregate_metrics.py +337 -0
- anyscale/client/openapi_client/models/task_job_group_aggregate.py +175 -0
- anyscale/client/openapi_client/models/task_job_group_aggregate_response.py +174 -0
- anyscale/client/openapi_client/models/task_state.py +103 -0
- anyscale/client/openapi_client/models/task_summary.py +256 -0
- anyscale/client/openapi_client/models/task_table_config.py +250 -0
- anyscale/client/openapi_client/models/task_table_response.py +174 -0
- anyscale/client/openapi_client/models/task_table_row.py +491 -0
- anyscale/client/openapi_client/models/task_type.py +100 -0
- anyscale/client/openapi_client/models/tasksummary_response.py +121 -0
- anyscale/cloud_resource.py +1 -1
- anyscale/cloud_utils.py +6 -2
- anyscale/cluster_compute.py +4 -3
- anyscale/cluster_env.py +8 -5
- anyscale/commands/command_examples.py +22 -0
- anyscale/compute_config/_private/compute_config_sdk.py +1 -1
- anyscale/connect_utils/prepare_cluster.py +14 -4
- anyscale/controllers/cloud_controller.py +2 -2
- anyscale/controllers/cloud_functional_verification_controller.py +4 -2
- anyscale/controllers/service_controller.py +1 -1
- anyscale/project_utils.py +4 -3
- anyscale/sdk/anyscale_client/models/baseimagesenum.py +2 -4
- anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +2 -2
- anyscale/sdk/anyscale_client/sdk.py +4 -4
- anyscale/utils/connect_helpers.py +16 -3
- anyscale/utils/runtime_env.py +3 -1
- anyscale/version.py +1 -1
- anyscale/workspace/__init__.py +10 -5
- anyscale/workspace/_private/workspace_sdk.py +4 -4
- anyscale/workspace/commands.py +1 -1
- {anyscale-0.26.13.dist-info → anyscale-0.26.15.dist-info}/METADATA +1 -1
- {anyscale-0.26.13.dist-info → anyscale-0.26.15.dist-info}/RECORD +53 -40
- anyscale/client/openapi_client/models/buffer_registration.py +0 -285
- {anyscale-0.26.13.dist-info → anyscale-0.26.15.dist-info}/LICENSE +0 -0
- {anyscale-0.26.13.dist-info → anyscale-0.26.15.dist-info}/NOTICE +0 -0
- {anyscale-0.26.13.dist-info → anyscale-0.26.15.dist-info}/WHEEL +0 -0
- {anyscale-0.26.13.dist-info → anyscale-0.26.15.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.13.dist-info → anyscale-0.26.15.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
"""
|
4
|
+
Managed Ray API
|
5
|
+
|
6
|
+
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
7
|
+
|
8
|
+
The version of the OpenAPI document: 0.1.0
|
9
|
+
Generated by: https://openapi-generator.tech
|
10
|
+
"""
|
11
|
+
|
12
|
+
|
13
|
+
import pprint
|
14
|
+
import re # noqa: F401
|
15
|
+
|
16
|
+
import six
|
17
|
+
|
18
|
+
from openapi_client.configuration import Configuration
|
19
|
+
|
20
|
+
|
21
|
+
class TaskType(object):
|
22
|
+
"""NOTE: This class is auto generated by OpenAPI Generator.
|
23
|
+
Ref: https://openapi-generator.tech
|
24
|
+
|
25
|
+
Do not edit the class manually.
|
26
|
+
"""
|
27
|
+
|
28
|
+
"""
|
29
|
+
allowed enum values
|
30
|
+
"""
|
31
|
+
NORMAL = "NORMAL"
|
32
|
+
ACTOR = "ACTOR"
|
33
|
+
|
34
|
+
allowable_values = [NORMAL, ACTOR] # noqa: E501
|
35
|
+
|
36
|
+
"""
|
37
|
+
Attributes:
|
38
|
+
openapi_types (dict): The key is attribute name
|
39
|
+
and the value is attribute type.
|
40
|
+
attribute_map (dict): The key is attribute name
|
41
|
+
and the value is json key in definition.
|
42
|
+
"""
|
43
|
+
openapi_types = {
|
44
|
+
}
|
45
|
+
|
46
|
+
attribute_map = {
|
47
|
+
}
|
48
|
+
|
49
|
+
def __init__(self, local_vars_configuration=None): # noqa: E501
|
50
|
+
"""TaskType - a model defined in OpenAPI""" # noqa: E501
|
51
|
+
if local_vars_configuration is None:
|
52
|
+
local_vars_configuration = Configuration()
|
53
|
+
self.local_vars_configuration = local_vars_configuration
|
54
|
+
self.discriminator = None
|
55
|
+
|
56
|
+
def to_dict(self):
|
57
|
+
"""Returns the model properties as a dict"""
|
58
|
+
result = {}
|
59
|
+
|
60
|
+
for attr, _ in six.iteritems(self.openapi_types):
|
61
|
+
value = getattr(self, attr)
|
62
|
+
if isinstance(value, list):
|
63
|
+
result[attr] = list(map(
|
64
|
+
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
|
65
|
+
value
|
66
|
+
))
|
67
|
+
elif hasattr(value, "to_dict"):
|
68
|
+
result[attr] = value.to_dict()
|
69
|
+
elif isinstance(value, dict):
|
70
|
+
result[attr] = dict(map(
|
71
|
+
lambda item: (item[0], item[1].to_dict())
|
72
|
+
if hasattr(item[1], "to_dict") else item,
|
73
|
+
value.items()
|
74
|
+
))
|
75
|
+
else:
|
76
|
+
result[attr] = value
|
77
|
+
|
78
|
+
return result
|
79
|
+
|
80
|
+
def to_str(self):
|
81
|
+
"""Returns the string representation of the model"""
|
82
|
+
return pprint.pformat(self.to_dict())
|
83
|
+
|
84
|
+
def __repr__(self):
|
85
|
+
"""For `print` and `pprint`"""
|
86
|
+
return self.to_str()
|
87
|
+
|
88
|
+
def __eq__(self, other):
|
89
|
+
"""Returns true if both objects are equal"""
|
90
|
+
if not isinstance(other, TaskType):
|
91
|
+
return False
|
92
|
+
|
93
|
+
return self.to_dict() == other.to_dict()
|
94
|
+
|
95
|
+
def __ne__(self, other):
|
96
|
+
"""Returns true if both objects are not equal"""
|
97
|
+
if not isinstance(other, TaskType):
|
98
|
+
return True
|
99
|
+
|
100
|
+
return self.to_dict() != other.to_dict()
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
"""
|
4
|
+
Managed Ray API
|
5
|
+
|
6
|
+
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
7
|
+
|
8
|
+
The version of the OpenAPI document: 0.1.0
|
9
|
+
Generated by: https://openapi-generator.tech
|
10
|
+
"""
|
11
|
+
|
12
|
+
|
13
|
+
import pprint
|
14
|
+
import re # noqa: F401
|
15
|
+
|
16
|
+
import six
|
17
|
+
|
18
|
+
from openapi_client.configuration import Configuration
|
19
|
+
|
20
|
+
|
21
|
+
class TasksummaryResponse(object):
|
22
|
+
"""NOTE: This class is auto generated by OpenAPI Generator.
|
23
|
+
Ref: https://openapi-generator.tech
|
24
|
+
|
25
|
+
Do not edit the class manually.
|
26
|
+
"""
|
27
|
+
|
28
|
+
"""
|
29
|
+
Attributes:
|
30
|
+
openapi_types (dict): The key is attribute name
|
31
|
+
and the value is attribute type.
|
32
|
+
attribute_map (dict): The key is attribute name
|
33
|
+
and the value is json key in definition.
|
34
|
+
"""
|
35
|
+
openapi_types = {
|
36
|
+
'result': 'TaskSummary'
|
37
|
+
}
|
38
|
+
|
39
|
+
attribute_map = {
|
40
|
+
'result': 'result'
|
41
|
+
}
|
42
|
+
|
43
|
+
def __init__(self, result=None, local_vars_configuration=None): # noqa: E501
|
44
|
+
"""TasksummaryResponse - a model defined in OpenAPI""" # noqa: E501
|
45
|
+
if local_vars_configuration is None:
|
46
|
+
local_vars_configuration = Configuration()
|
47
|
+
self.local_vars_configuration = local_vars_configuration
|
48
|
+
|
49
|
+
self._result = None
|
50
|
+
self.discriminator = None
|
51
|
+
|
52
|
+
self.result = result
|
53
|
+
|
54
|
+
@property
|
55
|
+
def result(self):
|
56
|
+
"""Gets the result of this TasksummaryResponse. # noqa: E501
|
57
|
+
|
58
|
+
|
59
|
+
:return: The result of this TasksummaryResponse. # noqa: E501
|
60
|
+
:rtype: TaskSummary
|
61
|
+
"""
|
62
|
+
return self._result
|
63
|
+
|
64
|
+
@result.setter
|
65
|
+
def result(self, result):
|
66
|
+
"""Sets the result of this TasksummaryResponse.
|
67
|
+
|
68
|
+
|
69
|
+
:param result: The result of this TasksummaryResponse. # noqa: E501
|
70
|
+
:type: TaskSummary
|
71
|
+
"""
|
72
|
+
if self.local_vars_configuration.client_side_validation and result is None: # noqa: E501
|
73
|
+
raise ValueError("Invalid value for `result`, must not be `None`") # noqa: E501
|
74
|
+
|
75
|
+
self._result = result
|
76
|
+
|
77
|
+
def to_dict(self):
|
78
|
+
"""Returns the model properties as a dict"""
|
79
|
+
result = {}
|
80
|
+
|
81
|
+
for attr, _ in six.iteritems(self.openapi_types):
|
82
|
+
value = getattr(self, attr)
|
83
|
+
if isinstance(value, list):
|
84
|
+
result[attr] = list(map(
|
85
|
+
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
|
86
|
+
value
|
87
|
+
))
|
88
|
+
elif hasattr(value, "to_dict"):
|
89
|
+
result[attr] = value.to_dict()
|
90
|
+
elif isinstance(value, dict):
|
91
|
+
result[attr] = dict(map(
|
92
|
+
lambda item: (item[0], item[1].to_dict())
|
93
|
+
if hasattr(item[1], "to_dict") else item,
|
94
|
+
value.items()
|
95
|
+
))
|
96
|
+
else:
|
97
|
+
result[attr] = value
|
98
|
+
|
99
|
+
return result
|
100
|
+
|
101
|
+
def to_str(self):
|
102
|
+
"""Returns the string representation of the model"""
|
103
|
+
return pprint.pformat(self.to_dict())
|
104
|
+
|
105
|
+
def __repr__(self):
|
106
|
+
"""For `print` and `pprint`"""
|
107
|
+
return self.to_str()
|
108
|
+
|
109
|
+
def __eq__(self, other):
|
110
|
+
"""Returns true if both objects are equal"""
|
111
|
+
if not isinstance(other, TasksummaryResponse):
|
112
|
+
return False
|
113
|
+
|
114
|
+
return self.to_dict() == other.to_dict()
|
115
|
+
|
116
|
+
def __ne__(self, other):
|
117
|
+
"""Returns true if both objects are not equal"""
|
118
|
+
if not isinstance(other, TasksummaryResponse):
|
119
|
+
return True
|
120
|
+
|
121
|
+
return self.to_dict() != other.to_dict()
|
anyscale/cloud_resource.py
CHANGED
@@ -71,7 +71,7 @@ def compare_dicts_diff(d1: Dict[Any, Any], d2: Dict[Any, Any]) -> str:
|
|
71
71
|
)
|
72
72
|
|
73
73
|
|
74
|
-
AWS_RESOURCE_DICT: Dict[str,
|
74
|
+
AWS_RESOURCE_DICT: Dict[str, str] = {
|
75
75
|
"VPC": CloudAnalyticsEventCloudResource.AWS_VPC,
|
76
76
|
"Subnet": CloudAnalyticsEventCloudResource.AWS_SUBNET,
|
77
77
|
"Security group": CloudAnalyticsEventCloudResource.AWS_SECURITY_GROUP,
|
anyscale/cloud_utils.py
CHANGED
@@ -11,6 +11,7 @@ from anyscale.client.openapi_client.models import (
|
|
11
11
|
CreateCloudResource,
|
12
12
|
CreateCloudResourceGCP,
|
13
13
|
)
|
14
|
+
from anyscale.sdk.anyscale_client.api.default_api import DefaultApi as SDKDefaultApi
|
14
15
|
from anyscale.sdk.anyscale_client.models.cloud import Cloud
|
15
16
|
|
16
17
|
|
@@ -114,7 +115,8 @@ def get_cloud_resource_by_cloud_id(
|
|
114
115
|
|
115
116
|
|
116
117
|
def get_last_used_cloud(
|
117
|
-
project_id: Optional[str],
|
118
|
+
project_id: Optional[str],
|
119
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
118
120
|
) -> str:
|
119
121
|
"""Return the name of the cloud last used in the project.
|
120
122
|
|
@@ -161,7 +163,9 @@ def get_last_used_cloud(
|
|
161
163
|
return cast(str, cloud_name)
|
162
164
|
|
163
165
|
|
164
|
-
def get_all_clouds(
|
166
|
+
def get_all_clouds(
|
167
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
168
|
+
) -> List[Cloud]:
|
165
169
|
"""Fetches all Clouds the user has access to.
|
166
170
|
Returns:
|
167
171
|
List of all Clouds the user has access to.
|
anyscale/cluster_compute.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import re
|
2
|
-
from typing import Optional, Tuple
|
2
|
+
from typing import Optional, Tuple, Union
|
3
3
|
|
4
4
|
from anyscale.authenticate import get_auth_api_client
|
5
5
|
from anyscale.cli_logger import BlockLogger
|
@@ -10,6 +10,7 @@ from anyscale.sdk.anyscale_client import (
|
|
10
10
|
ComputeTemplateConfig,
|
11
11
|
CreateComputeTemplate,
|
12
12
|
)
|
13
|
+
from anyscale.sdk.anyscale_client.api.default_api import DefaultApi as SDKDefaultApi
|
13
14
|
from anyscale.sdk.anyscale_client.models.cluster_compute_config import (
|
14
15
|
ClusterComputeConfig,
|
15
16
|
)
|
@@ -27,7 +28,7 @@ def get_default_cluster_compute(
|
|
27
28
|
cloud_name: Optional[str],
|
28
29
|
project_id: Optional[str],
|
29
30
|
api_client: Optional[DefaultApi] = None,
|
30
|
-
anyscale_api_client: Optional[DefaultApi] = None,
|
31
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
31
32
|
) -> ComputeTemplate:
|
32
33
|
if api_client is None:
|
33
34
|
api_client = get_auth_api_client().api_client
|
@@ -134,7 +135,7 @@ def register_compute_template(
|
|
134
135
|
|
135
136
|
def get_selected_cloud_id_or_default(
|
136
137
|
api_client: Optional[DefaultApi] = None,
|
137
|
-
anyscale_api_client: Optional[DefaultApi] = None,
|
138
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
138
139
|
cluster_compute_id: Optional[str] = None,
|
139
140
|
cluster_compute_config: Optional[ClusterComputeConfig] = None,
|
140
141
|
cloud_id: Optional[str] = None,
|
anyscale/cluster_env.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import List, Optional
|
1
|
+
from typing import List, Optional, Union
|
2
2
|
|
3
3
|
import click
|
4
4
|
|
@@ -6,6 +6,7 @@ from anyscale.authenticate import get_auth_api_client
|
|
6
6
|
from anyscale.cli_logger import BlockLogger
|
7
7
|
from anyscale.client.openapi_client.api.default_api import DefaultApi
|
8
8
|
from anyscale.sdk.anyscale_client import ClusterEnvironmentBuild
|
9
|
+
from anyscale.sdk.anyscale_client.api.default_api import DefaultApi as SDKDefaultApi
|
9
10
|
from anyscale.shared_anyscale_utils.utils.byod import is_byod_id
|
10
11
|
from anyscale.util import get_endpoint, get_ray_and_py_version_for_default_cluster_env
|
11
12
|
|
@@ -15,7 +16,7 @@ log = BlockLogger()
|
|
15
16
|
|
16
17
|
def get_default_cluster_env_build(
|
17
18
|
api_client: Optional[DefaultApi] = None,
|
18
|
-
anyscale_api_client: Optional[DefaultApi] = None,
|
19
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
19
20
|
) -> ClusterEnvironmentBuild:
|
20
21
|
ray_version, py_version = get_ray_and_py_version_for_default_cluster_env()
|
21
22
|
|
@@ -38,7 +39,8 @@ def get_default_cluster_env_build(
|
|
38
39
|
|
39
40
|
|
40
41
|
def get_build_from_cluster_env_identifier(
|
41
|
-
cluster_env_identifier: str,
|
42
|
+
cluster_env_identifier: str,
|
43
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
42
44
|
) -> ClusterEnvironmentBuild:
|
43
45
|
"""
|
44
46
|
Get a build id from a cluster environment identifier of form `my_cluster_env:1` or
|
@@ -103,7 +105,8 @@ def get_build_from_cluster_env_identifier(
|
|
103
105
|
|
104
106
|
|
105
107
|
def get_cluster_env_from_name(
|
106
|
-
cluster_env_name: str,
|
108
|
+
cluster_env_name: str,
|
109
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
107
110
|
) -> ClusterEnvironmentBuild:
|
108
111
|
"""
|
109
112
|
Get id of the cluster env (not build) given the name.
|
@@ -123,7 +126,7 @@ def get_cluster_env_from_name(
|
|
123
126
|
|
124
127
|
def list_builds(
|
125
128
|
cluster_env_id: str,
|
126
|
-
anyscale_api_client: Optional[DefaultApi] = None,
|
129
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
127
130
|
max_items: Optional[int] = None,
|
128
131
|
) -> List[ClusterEnvironmentBuild]:
|
129
132
|
"""
|
@@ -1,4 +1,5 @@
|
|
1
1
|
JOB_SUBMIT_EXAMPLE = """\
|
2
|
+
# Submit a job without a yaml file, this will inherit the environment from the workspace.
|
2
3
|
$ anyscale job submit --name my-job --wait -- python main.py
|
3
4
|
Output
|
4
5
|
(anyscale +1.0s) Submitting job with config JobConfig(name='my-job', image_uri=None, compute_config=None, env_vars=None, py_modules=None, cloud=None, project=None, ray_version=None, job_queue_config=None).
|
@@ -10,6 +11,27 @@ Output
|
|
10
11
|
(anyscale +3.5s) Waiting for job 'prodjob_6ntzknwk1i9b1uw1zk1gp9dbhe' to reach target state SUCCEEDED, currently in state: STARTING
|
11
12
|
(anyscale +1m19.7s) Job 'prodjob_6ntzknwk1i9b1uw1zk1gp9dbhe' transitioned from STARTING to SUCCEEDED
|
12
13
|
(anyscale +1m19.7s) Job 'prodjob_6ntzknwk1i9b1uw1zk1gp9dbhe' reached target state, exiting
|
14
|
+
|
15
|
+
# Submit a job specified by a yaml file, this will run a job with the specified settings.
|
16
|
+
# See https://docs.anyscale.com/reference/job-api/#jobconfig for a list of all available fields.
|
17
|
+
$ cat job.yaml
|
18
|
+
name: my-job
|
19
|
+
entrypoint: python main.py
|
20
|
+
image_uri: anyscale/ray:2.44.1-slim-py312-cu128 # (Optional) Exclusive with `containerfile`.
|
21
|
+
# compute_config: # (Optional) An inline dictionary can also be provided.
|
22
|
+
# head_node:
|
23
|
+
# instance_type: m5.8xlarge
|
24
|
+
working_dir: . # (Optional) Use current working directory "." as the working_dir. Can be any local path or remote .zip file in cloud storage.
|
25
|
+
requirements: # (Optional) List of requirements files to install. Can also be a path to a requirements.txt.
|
26
|
+
- emoji
|
27
|
+
max_retries: 0 # (Optional) Maximum number of times the job will be retried before being marked failed. Defaults to `1`.
|
28
|
+
$ anyscale job submit -f job.yaml
|
29
|
+
Output
|
30
|
+
(anyscale +1.0s) Submitting job with config JobConfig(name='my-job', image_uri='anyscale/ray:2.44.1-slim-py312-cu128', compute_config=None, env_vars=None, py_modules=None, py_executable=None, cloud=None, project=None, ray_version=None, job_queue_config=None).
|
31
|
+
(anyscale +4.2s) Uploading local dir '.' to cloud storage.
|
32
|
+
(anyscale +5.4s) Job 'my-job' submitted, ID: 'prodjob_ugk21r7pt6sbsxfuxn1an82x3e'.
|
33
|
+
(anyscale +5.4s) View the job in the UI: https://console.anyscale.com/jobs/prodjob_ugk21r7pt6sbsxfuxn1an82x3e
|
34
|
+
(anyscale +5.4s) Use `--wait` to wait for the job to run and stream logs.
|
13
35
|
"""
|
14
36
|
|
15
37
|
JOB_STATUS_EXAMPLE = """\
|
@@ -154,7 +154,7 @@ class PrivateComputeConfigSDK(BaseSDK):
|
|
154
154
|
# `worker_nodes=None` uses the default serverless config, so this only happens if `worker_nodes`
|
155
155
|
# is explicitly set to an empty list.
|
156
156
|
# Returns the default cloud if user-provided cloud is not specified (`None`).
|
157
|
-
cloud_id = self.client.get_cloud_id(cloud_name=compute_config.cloud)
|
157
|
+
cloud_id = self.client.get_cloud_id(cloud_name=compute_config.cloud) # type: ignore
|
158
158
|
cloud = self.client.get_cloud(cloud_id=cloud_id)
|
159
159
|
if cloud is None:
|
160
160
|
raise RuntimeError(
|
@@ -275,11 +275,21 @@ class PrepareClusterBlock:
|
|
275
275
|
# Try to generate an auto-incrementing cluster name from the first 100 clusters.
|
276
276
|
# If there are more than 40 clusters with, we will generate a random name.
|
277
277
|
# If the name is already taken, we will re-try with a different random name.
|
278
|
-
|
279
|
-
|
280
|
-
|
278
|
+
used_names: List[str] = []
|
279
|
+
has_more = True
|
280
|
+
paging_token = None
|
281
|
+
while has_more:
|
282
|
+
resp = self.anyscale_api_client.search_clusters(
|
283
|
+
clusters_query={
|
284
|
+
"project_id": project_id,
|
285
|
+
"paging": {"count": 50, "paging_token": paging_token},
|
286
|
+
}
|
287
|
+
)
|
288
|
+
used_names.extend([c.name for c in resp.results])
|
289
|
+
paging_token = resp.metadata.next_paging_token
|
290
|
+
has_more = paging_token is not None
|
291
|
+
|
281
292
|
self.log.debug("-> Starting a new cluster")
|
282
|
-
used_names = [s.name for s in results]
|
283
293
|
for i in range(MAX_CLUSTERS):
|
284
294
|
name = f"cluster-{i}"
|
285
295
|
if name not in used_names:
|
@@ -3243,7 +3243,7 @@ class CloudController(BaseController):
|
|
3243
3243
|
*,
|
3244
3244
|
cloud_resource: Any,
|
3245
3245
|
edit_details: Dict[str, Optional[str]],
|
3246
|
-
gcp_filestore_config: GCPFileStoreConfig,
|
3246
|
+
gcp_filestore_config: Optional[GCPFileStoreConfig],
|
3247
3247
|
gcp_filestore_instance_id: Optional[str],
|
3248
3248
|
gcp_filestore_location: Optional[str],
|
3249
3249
|
gcp_utils,
|
@@ -3276,7 +3276,7 @@ class CloudController(BaseController):
|
|
3276
3276
|
cloud_id: str,
|
3277
3277
|
cloud_resource: Any,
|
3278
3278
|
edit_details: Dict[str, Optional[str]],
|
3279
|
-
gcp_filestore_config: GCPFileStoreConfig,
|
3279
|
+
gcp_filestore_config: Optional[GCPFileStoreConfig],
|
3280
3280
|
gcp_utils,
|
3281
3281
|
):
|
3282
3282
|
rollback_cmd = self._generate_rollback_command(
|
@@ -820,11 +820,13 @@ class CloudFunctionalVerificationController(BaseController):
|
|
820
820
|
)
|
821
821
|
|
822
822
|
confirmation_message.append(
|
823
|
-
"The instances will be terminated after verification.
|
823
|
+
"The instances will be terminated after verification."
|
824
824
|
)
|
825
825
|
|
826
|
+
self.log.info("\n".join(confirmation_message))
|
827
|
+
|
826
828
|
confirm(
|
827
|
-
"
|
829
|
+
"Continue?", yes,
|
828
830
|
)
|
829
831
|
|
830
832
|
verification_results: List[bool] = []
|
@@ -342,7 +342,7 @@ class ServiceController(BaseController):
|
|
342
342
|
def _overwrite_runtime_env_in_v2_ray_serve_config(self, config: ServiceConfig):
|
343
343
|
"""Modifies config in place."""
|
344
344
|
ray_serve_config = config.ray_serve_config
|
345
|
-
if "applications" in ray_serve_config:
|
345
|
+
if ray_serve_config is not None and "applications" in ray_serve_config:
|
346
346
|
for ray_serve_app_config in ray_serve_config["applications"]:
|
347
347
|
ray_serve_app_config["runtime_env"] = override_runtime_env_config(
|
348
348
|
runtime_env=ray_serve_app_config.get("runtime_env"),
|
anyscale/project_utils.py
CHANGED
@@ -14,6 +14,7 @@ from anyscale.cluster_compute import (
|
|
14
14
|
get_cluster_compute_from_name,
|
15
15
|
get_selected_cloud_id_or_default,
|
16
16
|
)
|
17
|
+
from anyscale.sdk.anyscale_client.api.default_api import DefaultApi as SDKDefaultApi
|
17
18
|
from anyscale.sdk.anyscale_client.models.cluster_compute_config import (
|
18
19
|
ClusterComputeConfig,
|
19
20
|
)
|
@@ -395,7 +396,7 @@ def get_and_validate_project_id(
|
|
395
396
|
project_name: Optional[str],
|
396
397
|
parent_cloud_id: Optional[str],
|
397
398
|
api_client: DefaultApi,
|
398
|
-
anyscale_api_client: DefaultApi,
|
399
|
+
anyscale_api_client: Union[DefaultApi, SDKDefaultApi],
|
399
400
|
) -> str:
|
400
401
|
project_name = project_name or os.environ.get(PROJECT_NAME_ENV_VAR)
|
401
402
|
if project_id:
|
@@ -421,7 +422,7 @@ def get_and_validate_project_id(
|
|
421
422
|
|
422
423
|
def get_default_project(
|
423
424
|
api_client: Optional[DefaultApi] = None,
|
424
|
-
anyscale_api_client: Optional[DefaultApi] = None,
|
425
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
425
426
|
parent_cloud_id: Optional[str] = None,
|
426
427
|
):
|
427
428
|
"""
|
@@ -448,7 +449,7 @@ def get_default_project(
|
|
448
449
|
|
449
450
|
|
450
451
|
def infer_project_id( # noqa PLR0913
|
451
|
-
anyscale_api_client: DefaultApi,
|
452
|
+
anyscale_api_client: Union[DefaultApi, SDKDefaultApi],
|
452
453
|
api_client: DefaultApi,
|
453
454
|
log: BlockLogger,
|
454
455
|
project_id: Optional[str],
|