anyscale 0.26.14__py3-none-any.whl → 0.26.16__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 +4 -2
- anyscale/_private/anyscale_client/common.py +6 -4
- anyscale/_private/anyscale_client/fake_anyscale_client.py +16 -7
- anyscale/_private/docgen/__main__.py +4 -4
- anyscale/_private/docgen/generator.py +2 -2
- anyscale/_private/models/model_base.py +5 -2
- anyscale/_private/sdk/__init__.py +2 -2
- anyscale/_private/utils/progress_util.py +2 -2
- anyscale/_private/workload/workload_sdk.py +10 -7
- anyscale/aggregated_instance_usage/commands.py +6 -2
- anyscale/anyscale-cloud-setup.yaml +4 -0
- anyscale/client/README.md +8 -11
- anyscale/client/openapi_client/__init__.py +6 -8
- anyscale/client/openapi_client/api/default_api.py +292 -377
- anyscale/client/openapi_client/models/__init__.py +6 -8
- anyscale/client/openapi_client/models/alert_type.py +11 -2
- anyscale/client/openapi_client/models/create_job_queue_requests.py +3 -32
- anyscale/client/openapi_client/models/{product_autoscaler_flag.py → list_ray_sessions_response.py} +22 -23
- anyscale/client/openapi_client/models/{productautoscalerflag_response.py → listraysessionsresponse_response.py} +11 -11
- anyscale/client/openapi_client/models/metric.py +133 -3
- anyscale/client/openapi_client/models/ray_session.py +121 -0
- anyscale/client/openapi_client/models/task_exception_group_aggregate.py +28 -1
- anyscale/client/openapi_client/models/{taskexceptiongroupaggregate_list_response.py → task_exception_group_aggregate_response.py} +52 -25
- anyscale/client/openapi_client/models/task_function_name_group_aggregate.py +28 -1
- anyscale/client/openapi_client/models/{taskfunctionnamegroupaggregate_list_response.py → task_function_name_group_aggregate_response.py} +52 -25
- anyscale/client/openapi_client/models/task_job_group_aggregate.py +28 -1
- anyscale/client/openapi_client/models/{taskjobgroupaggregate_list_response.py → task_job_group_aggregate_response.py} +52 -25
- anyscale/client/openapi_client/models/task_table_row.py +19 -19
- anyscale/cloud/__init__.py +2 -2
- anyscale/cloud/_private/cloud_sdk.py +2 -2
- anyscale/cloud/commands.py +9 -6
- anyscale/cloud_resource.py +1 -1
- anyscale/cloud_utils.py +11 -6
- anyscale/cluster_compute.py +6 -5
- anyscale/cluster_env.py +10 -5
- anyscale/commands/login_commands.py +24 -3
- anyscale/commands/schedule_commands.py +2 -1
- anyscale/compute_config/_private/compute_config_sdk.py +1 -1
- anyscale/compute_config/commands.py +15 -7
- anyscale/connect_utils/prepare_cluster.py +14 -4
- anyscale/controllers/cloud_controller.py +9 -9
- anyscale/controllers/cloud_functional_verification_controller.py +4 -2
- anyscale/controllers/cluster_controller.py +1 -0
- anyscale/controllers/job_controller.py +1 -1
- anyscale/controllers/service_controller.py +2 -1
- anyscale/image/commands.py +6 -6
- anyscale/job/commands.py +12 -12
- anyscale/organization_invitation/commands.py +11 -7
- anyscale/project/__init__.py +2 -2
- anyscale/project/_private/project_sdk.py +2 -2
- anyscale/project/commands.py +3 -3
- anyscale/project_utils.py +5 -4
- anyscale/resource_quota/commands.py +18 -10
- anyscale/schedule/commands.py +12 -8
- anyscale/sdk/anyscale_client/sdk.py +5 -4
- anyscale/service/commands.py +17 -17
- anyscale/service_account/commands.py +12 -10
- anyscale/user/commands.py +5 -3
- anyscale/utils/connect_helpers.py +16 -3
- anyscale/utils/gcp_utils.py +25 -9
- anyscale/utils/runtime_env.py +3 -1
- anyscale/version.py +1 -1
- anyscale/workspace/__init__.py +10 -5
- anyscale/workspace/_private/workspace_sdk.py +9 -7
- anyscale/workspace/commands.py +25 -23
- {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/METADATA +1 -1
- {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/RECORD +72 -74
- anyscale/client/openapi_client/models/aviary_model_config_v2.py +0 -358
- anyscale/client/openapi_client/models/buffer_registration.py +0 -285
- anyscale/client/openapi_client/models/finish_ft_job_request_v2.py +0 -183
- {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/LICENSE +0 -0
- {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/NOTICE +0 -0
- {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/WHEEL +0 -0
- {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/top_level.txt +0 -0
@@ -42,12 +42,12 @@ class TaskTableRow(object):
|
|
42
42
|
'error_message': 'str',
|
43
43
|
'start_time_ns': 'int',
|
44
44
|
'end_time_ns': 'int',
|
45
|
-
'required_resources': '
|
45
|
+
'required_resources': 'str',
|
46
46
|
'node_id': 'str',
|
47
47
|
'worker_id': 'str',
|
48
48
|
'worker_pid': 'str',
|
49
49
|
'parent_task_id': 'str',
|
50
|
-
'
|
50
|
+
'ray_session_name': 'str'
|
51
51
|
}
|
52
52
|
|
53
53
|
attribute_map = {
|
@@ -65,10 +65,10 @@ class TaskTableRow(object):
|
|
65
65
|
'worker_id': 'worker_id',
|
66
66
|
'worker_pid': 'worker_pid',
|
67
67
|
'parent_task_id': 'parent_task_id',
|
68
|
-
'
|
68
|
+
'ray_session_name': 'ray_session_name'
|
69
69
|
}
|
70
70
|
|
71
|
-
def __init__(self, id=None, attempt_number=None, job_id=None, function_name=None, task_type=None, current_state=None, error_message=None, start_time_ns=None, end_time_ns=None, required_resources=None, node_id=None, worker_id=None, worker_pid=None, parent_task_id=None,
|
71
|
+
def __init__(self, id=None, attempt_number=None, job_id=None, function_name=None, task_type=None, current_state=None, error_message=None, start_time_ns=None, end_time_ns=None, required_resources=None, node_id=None, worker_id=None, worker_pid=None, parent_task_id=None, ray_session_name=None, local_vars_configuration=None): # noqa: E501
|
72
72
|
"""TaskTableRow - a model defined in OpenAPI""" # noqa: E501
|
73
73
|
if local_vars_configuration is None:
|
74
74
|
local_vars_configuration = Configuration()
|
@@ -88,7 +88,7 @@ class TaskTableRow(object):
|
|
88
88
|
self._worker_id = None
|
89
89
|
self._worker_pid = None
|
90
90
|
self._parent_task_id = None
|
91
|
-
self.
|
91
|
+
self._ray_session_name = None
|
92
92
|
self.discriminator = None
|
93
93
|
|
94
94
|
self.id = id
|
@@ -113,7 +113,7 @@ class TaskTableRow(object):
|
|
113
113
|
self.worker_pid = worker_pid
|
114
114
|
if parent_task_id is not None:
|
115
115
|
self.parent_task_id = parent_task_id
|
116
|
-
self.
|
116
|
+
self.ray_session_name = ray_session_name
|
117
117
|
|
118
118
|
@property
|
119
119
|
def id(self):
|
@@ -322,7 +322,7 @@ class TaskTableRow(object):
|
|
322
322
|
|
323
323
|
|
324
324
|
:return: The required_resources of this TaskTableRow. # noqa: E501
|
325
|
-
:rtype:
|
325
|
+
:rtype: str
|
326
326
|
"""
|
327
327
|
return self._required_resources
|
328
328
|
|
@@ -332,7 +332,7 @@ class TaskTableRow(object):
|
|
332
332
|
|
333
333
|
|
334
334
|
:param required_resources: The required_resources of this TaskTableRow. # noqa: E501
|
335
|
-
:type:
|
335
|
+
:type: str
|
336
336
|
"""
|
337
337
|
|
338
338
|
self._required_resources = required_resources
|
@@ -422,27 +422,27 @@ class TaskTableRow(object):
|
|
422
422
|
self._parent_task_id = parent_task_id
|
423
423
|
|
424
424
|
@property
|
425
|
-
def
|
426
|
-
"""Gets the
|
425
|
+
def ray_session_name(self):
|
426
|
+
"""Gets the ray_session_name of this TaskTableRow. # noqa: E501
|
427
427
|
|
428
428
|
|
429
|
-
:return: The
|
429
|
+
:return: The ray_session_name of this TaskTableRow. # noqa: E501
|
430
430
|
:rtype: str
|
431
431
|
"""
|
432
|
-
return self.
|
432
|
+
return self._ray_session_name
|
433
433
|
|
434
|
-
@
|
435
|
-
def
|
436
|
-
"""Sets the
|
434
|
+
@ray_session_name.setter
|
435
|
+
def ray_session_name(self, ray_session_name):
|
436
|
+
"""Sets the ray_session_name of this TaskTableRow.
|
437
437
|
|
438
438
|
|
439
|
-
:param
|
439
|
+
:param ray_session_name: The ray_session_name of this TaskTableRow. # noqa: E501
|
440
440
|
:type: str
|
441
441
|
"""
|
442
|
-
if self.local_vars_configuration.client_side_validation and
|
443
|
-
raise ValueError("Invalid value for `
|
442
|
+
if self.local_vars_configuration.client_side_validation and ray_session_name is None: # noqa: E501
|
443
|
+
raise ValueError("Invalid value for `ray_session_name`, must not be `None`") # noqa: E501
|
444
444
|
|
445
|
-
self.
|
445
|
+
self._ray_session_name = ray_session_name
|
446
446
|
|
447
447
|
def to_dict(self):
|
448
448
|
"""Returns the model properties as a dict"""
|
anyscale/cloud/__init__.py
CHANGED
@@ -38,14 +38,14 @@ class CloudSDK:
|
|
38
38
|
)
|
39
39
|
def add_collaborators(
|
40
40
|
self, cloud: str, collaborators: List[CreateCloudCollaborator],
|
41
|
-
) ->
|
41
|
+
) -> None:
|
42
42
|
"""
|
43
43
|
Batch add collaborators to a cloud.
|
44
44
|
|
45
45
|
:param cloud: The cloud to add users to.
|
46
46
|
:param collaborators: The list of collaborators to add to the cloud.
|
47
47
|
"""
|
48
|
-
|
48
|
+
self._private_sdk.add_collaborators(cloud, collaborators)
|
49
49
|
|
50
50
|
@sdk_docs(
|
51
51
|
doc_py_example=_GET_EXAMPLE, arg_docstrings=_GET_ARG_DOCSTRINGS,
|
@@ -16,10 +16,10 @@ from anyscale.cloud.models import (
|
|
16
16
|
class PrivateCloudSDK(BaseSDK):
|
17
17
|
def add_collaborators(
|
18
18
|
self, cloud: str, collaborators: List[CreateCloudCollaborator]
|
19
|
-
) ->
|
19
|
+
) -> None:
|
20
20
|
cloud_id = self.client.get_cloud_id(cloud_name=cloud, compute_config_id=None)
|
21
21
|
|
22
|
-
|
22
|
+
self.client.add_cloud_collaborators(
|
23
23
|
cloud_id=cloud_id,
|
24
24
|
collaborators=[
|
25
25
|
CreateCloudCollaboratorModel(
|
anyscale/cloud/commands.py
CHANGED
@@ -39,7 +39,10 @@ _ADD_COLLABORATORS_ARG_DOCSTRINGS = {
|
|
39
39
|
arg_docstrings=_ADD_COLLABORATORS_ARG_DOCSTRINGS,
|
40
40
|
)
|
41
41
|
def add_collaborators(
|
42
|
-
cloud: str,
|
42
|
+
cloud: str,
|
43
|
+
collaborators: List[CreateCloudCollaborator],
|
44
|
+
*,
|
45
|
+
_private_sdk: Optional[PrivateCloudSDK] = None,
|
43
46
|
) -> str:
|
44
47
|
"""
|
45
48
|
Batch add collaborators to a cloud.
|
@@ -47,7 +50,7 @@ def add_collaborators(
|
|
47
50
|
:param cloud: The cloud to add users to.
|
48
51
|
:param collaborators: The list of collaborators to add to the cloud.
|
49
52
|
"""
|
50
|
-
return
|
53
|
+
return _private_sdk.add_collaborators(cloud, collaborators) # type: ignore
|
51
54
|
|
52
55
|
|
53
56
|
_GET_EXAMPLE = """
|
@@ -76,7 +79,7 @@ def get(
|
|
76
79
|
id: Optional[str] = None, # noqa: A002
|
77
80
|
name: Optional[str] = None,
|
78
81
|
*,
|
79
|
-
|
82
|
+
_private_sdk: Optional[PrivateCloudSDK] = None,
|
80
83
|
) -> Optional[Cloud]:
|
81
84
|
"""
|
82
85
|
Get the cloud model for the provided cloud ID or name.
|
@@ -87,7 +90,7 @@ def get(
|
|
87
90
|
:param name: The name of the cloud to retrieve.
|
88
91
|
:return: A `Cloud` object if found, otherwise `None`.
|
89
92
|
"""
|
90
|
-
return
|
93
|
+
return _private_sdk.get(id=id, name=name) # type: ignore
|
91
94
|
|
92
95
|
|
93
96
|
_GET_DEFAULT_EXAMPLE = """
|
@@ -104,10 +107,10 @@ default_cloud = anyscale.cloud.get_default()
|
|
104
107
|
doc_py_example=_GET_DEFAULT_EXAMPLE,
|
105
108
|
arg_docstrings={},
|
106
109
|
)
|
107
|
-
def get_default(*,
|
110
|
+
def get_default(*, _private_sdk: Optional[PrivateCloudSDK] = None) -> Optional[Cloud]:
|
108
111
|
"""
|
109
112
|
Get the user's default cloud.
|
110
113
|
|
111
114
|
:return: The default `Cloud` object if it exists, otherwise `None`.
|
112
115
|
"""
|
113
|
-
return
|
116
|
+
return _private_sdk.get_default() # type: ignore
|
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
|
|
@@ -99,6 +100,7 @@ def get_cloud_resource_by_cloud_id(
|
|
99
100
|
) -> Union[CreateCloudResource, CreateCloudResourceGCP]:
|
100
101
|
if anyscale_api_client is None:
|
101
102
|
anyscale_api_client = get_auth_api_client().anyscale_api_client
|
103
|
+
assert anyscale_api_client is not None
|
102
104
|
cloud_resource = None
|
103
105
|
if cloud_provider == "AWS":
|
104
106
|
cloud = anyscale_api_client.get_cloud_with_cloud_resource_api_v2_clouds_with_cloud_resource_router_cloud_id_get(
|
@@ -114,7 +116,8 @@ def get_cloud_resource_by_cloud_id(
|
|
114
116
|
|
115
117
|
|
116
118
|
def get_last_used_cloud(
|
117
|
-
project_id: Optional[str],
|
119
|
+
project_id: Optional[str],
|
120
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
118
121
|
) -> str:
|
119
122
|
"""Return the name of the cloud last used in the project.
|
120
123
|
|
@@ -131,12 +134,12 @@ def get_last_used_cloud(
|
|
131
134
|
if anyscale_api_client is None:
|
132
135
|
anyscale_api_client = get_auth_api_client().anyscale_api_client
|
133
136
|
if project_id:
|
134
|
-
cloud_id = anyscale_api_client.get_project(project_id).result.last_used_cloud_id
|
137
|
+
cloud_id = anyscale_api_client.get_project(project_id).result.last_used_cloud_id # type: ignore
|
135
138
|
else:
|
136
139
|
cloud_id = None
|
137
140
|
if cloud_id:
|
138
141
|
try:
|
139
|
-
cloud = anyscale_api_client.get_cloud(cloud_id).result
|
142
|
+
cloud = anyscale_api_client.get_cloud(cloud_id).result # type: ignore
|
140
143
|
except Exception: # noqa: BLE001
|
141
144
|
raise click.ClickException(
|
142
145
|
f"Failed to fetch Cloud with id: {cloud_id}. Please specify `cloud` in the command."
|
@@ -161,7 +164,9 @@ def get_last_used_cloud(
|
|
161
164
|
return cast(str, cloud_name)
|
162
165
|
|
163
166
|
|
164
|
-
def get_all_clouds(
|
167
|
+
def get_all_clouds(
|
168
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
169
|
+
) -> List[Cloud]:
|
165
170
|
"""Fetches all Clouds the user has access to.
|
166
171
|
Returns:
|
167
172
|
List of all Clouds the user has access to.
|
@@ -171,12 +176,12 @@ def get_all_clouds(anyscale_api_client: Optional[DefaultApi] = None) -> List[Clo
|
|
171
176
|
if anyscale_api_client is None:
|
172
177
|
anyscale_api_client = get_auth_api_client().anyscale_api_client
|
173
178
|
|
174
|
-
cloud_list_response = anyscale_api_client.search_clouds({"paging": {"count": 50}})
|
179
|
+
cloud_list_response = anyscale_api_client.search_clouds({"paging": {"count": 50}}) # type: ignore
|
175
180
|
all_clouds = cloud_list_response.results
|
176
181
|
next_paging_token = cloud_list_response.metadata.next_paging_token
|
177
182
|
|
178
183
|
while next_paging_token:
|
179
|
-
cloud_list_response = anyscale_api_client.search_clouds(
|
184
|
+
cloud_list_response = anyscale_api_client.search_clouds( # type: ignore
|
180
185
|
{"paging": {"count": 50, "paging_token": next_paging_token}}
|
181
186
|
)
|
182
187
|
next_paging_token = cloud_list_response.metadata.next_paging_token
|
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
|
@@ -42,7 +43,7 @@ def get_default_cluster_compute(
|
|
42
43
|
cloud_name = get_last_used_cloud(project_id, anyscale_api_client)
|
43
44
|
|
44
45
|
cloud_id, _ = get_cloud_id_and_name(api_client, cloud_name=cloud_name)
|
45
|
-
config_object = anyscale_api_client.get_default_compute_config(cloud_id).result
|
46
|
+
config_object = anyscale_api_client.get_default_compute_config(cloud_id).result # type: ignore
|
46
47
|
compute_template = register_compute_template(config_object, api_client=api_client)
|
47
48
|
return compute_template
|
48
49
|
|
@@ -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,
|
@@ -155,7 +156,7 @@ def get_selected_cloud_id_or_default(
|
|
155
156
|
api_client=api_client, cloud_id=cloud_id, cloud_name=cloud_name,
|
156
157
|
)
|
157
158
|
elif cluster_compute_id:
|
158
|
-
parent_cloud_id = anyscale_api_client.get_cluster_compute(
|
159
|
+
parent_cloud_id = anyscale_api_client.get_cluster_compute( # type: ignore
|
159
160
|
cluster_compute_id
|
160
161
|
).result.config.cloud_id
|
161
162
|
elif cluster_compute_config:
|
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.
|
@@ -111,6 +114,7 @@ def get_cluster_env_from_name(
|
|
111
114
|
|
112
115
|
if anyscale_api_client is None:
|
113
116
|
anyscale_api_client = get_auth_api_client().anyscale_api_client
|
117
|
+
assert anyscale_api_client is not None
|
114
118
|
cluster_envs = anyscale_api_client.search_cluster_environments(
|
115
119
|
{"name": {"equals": cluster_env_name}, "paging": {"count": 1}}
|
116
120
|
).results
|
@@ -123,7 +127,7 @@ def get_cluster_env_from_name(
|
|
123
127
|
|
124
128
|
def list_builds(
|
125
129
|
cluster_env_id: str,
|
126
|
-
anyscale_api_client: Optional[DefaultApi] = None,
|
130
|
+
anyscale_api_client: Optional[Union[DefaultApi, SDKDefaultApi]] = None,
|
127
131
|
max_items: Optional[int] = None,
|
128
132
|
) -> List[ClusterEnvironmentBuild]:
|
129
133
|
"""
|
@@ -161,6 +165,7 @@ def validate_successful_build(
|
|
161
165
|
|
162
166
|
if anyscale_api_client is None:
|
163
167
|
anyscale_api_client = get_auth_api_client().anyscale_api_client
|
168
|
+
assert anyscale_api_client is not None
|
164
169
|
build = anyscale_api_client.get_cluster_environment_build(build_id).result
|
165
170
|
if build.status != "succeeded":
|
166
171
|
cluster_env = anyscale_api_client.get_cluster_environment(
|
@@ -32,7 +32,10 @@ def get_unauthenticated_openapi_client():
|
|
32
32
|
default=7,
|
33
33
|
help="Expire the token after this many days.",
|
34
34
|
)
|
35
|
-
|
35
|
+
@click.option(
|
36
|
+
"--no-browser", is_flag=True, default=False, help="Do not open the browser.",
|
37
|
+
)
|
38
|
+
def anyscale_login(no_expire: bool, expire_in_days: int, no_browser: bool) -> None:
|
36
39
|
"""Log in to Anyscale using a URL
|
37
40
|
This is the only unauthenticated API usage in the CLI."""
|
38
41
|
if expire_in_days < 0 or no_expire:
|
@@ -52,8 +55,26 @@ def anyscale_login(no_expire: bool, expire_in_days: int) -> None:
|
|
52
55
|
|
53
56
|
# Open the URL in the browser. This will work on most platforms.
|
54
57
|
# OK to suppress any uncaught exceptions, because the URL will be printed out anyway.
|
55
|
-
|
56
|
-
|
58
|
+
if not no_browser:
|
59
|
+
with contextlib.suppress(Exception):
|
60
|
+
try:
|
61
|
+
# Only attempt to open browser if it's not a CLI browser (which doesn't support JavaScript)
|
62
|
+
if webbrowser.get().basename not in [
|
63
|
+
"www-browser",
|
64
|
+
"elinks",
|
65
|
+
"links",
|
66
|
+
"lynx",
|
67
|
+
"w3m",
|
68
|
+
]:
|
69
|
+
webbrowser.open_new_tab(r.url)
|
70
|
+
else:
|
71
|
+
log.info(
|
72
|
+
"Could not open a JavaScript-capable web browser. Open the above URL in your browser manually."
|
73
|
+
)
|
74
|
+
except webbrowser.Error:
|
75
|
+
log.info(
|
76
|
+
"Could not open a web browser. Open the above URL in your browser manually."
|
77
|
+
)
|
57
78
|
|
58
79
|
# give user 3 minutes to log in (3 seconds per attempt)
|
59
80
|
for _i in range(60):
|
@@ -11,7 +11,7 @@ from anyscale.cli_logger import BlockLogger
|
|
11
11
|
from anyscale.commands import command_examples
|
12
12
|
from anyscale.commands.util import AnyscaleCommand, LegacyAnyscaleCommand
|
13
13
|
from anyscale.controllers.schedule_controller import ScheduleController
|
14
|
-
from anyscale.schedule.models import ScheduleConfig, ScheduleState
|
14
|
+
from anyscale.schedule.models import JobConfig, ScheduleConfig, ScheduleState
|
15
15
|
|
16
16
|
|
17
17
|
log = BlockLogger() # CLI Logger
|
@@ -85,6 +85,7 @@ def apply(config_file: str, name: Optional[str],) -> None:
|
|
85
85
|
config = ScheduleConfig.from_yaml(config_file)
|
86
86
|
|
87
87
|
if name is not None:
|
88
|
+
assert isinstance(config.job_config, JobConfig)
|
88
89
|
config = config.options(job_config=config.job_config.options(name=name),)
|
89
90
|
|
90
91
|
log.info(f"Applying schedule with config {config}.")
|
@@ -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(
|
@@ -45,13 +45,16 @@ _CREATE_ARG_DOCSTRINGS = {
|
|
45
45
|
arg_docstrings=_CREATE_ARG_DOCSTRINGS,
|
46
46
|
)
|
47
47
|
def create(
|
48
|
-
config: ComputeConfig,
|
48
|
+
config: ComputeConfig,
|
49
|
+
*,
|
50
|
+
name: Optional[str],
|
51
|
+
_private_sdk: Optional[PrivateComputeConfigSDK] = None,
|
49
52
|
) -> str:
|
50
53
|
"""Create a new version of a compute config.
|
51
54
|
|
52
55
|
Returns the full name of the registered compute config, including the version.
|
53
56
|
"""
|
54
|
-
full_name, _ =
|
57
|
+
full_name, _ = _private_sdk.create_compute_config(config, name=name) # type: ignore
|
55
58
|
return full_name
|
56
59
|
|
57
60
|
|
@@ -74,11 +77,11 @@ _GET_ARG_DOCSTRINGS = {
|
|
74
77
|
arg_docstrings=_GET_ARG_DOCSTRINGS,
|
75
78
|
)
|
76
79
|
def get(
|
77
|
-
name: str,
|
80
|
+
name: Optional[str],
|
78
81
|
*,
|
79
82
|
include_archived: bool = False,
|
80
83
|
_id: Optional[str] = None,
|
81
|
-
|
84
|
+
_private_sdk: Optional[PrivateComputeConfigSDK] = None,
|
82
85
|
) -> ComputeConfigVersion:
|
83
86
|
"""Get the compute config with the specified name.
|
84
87
|
|
@@ -88,7 +91,7 @@ def get(
|
|
88
91
|
# NOTE(edoakes): I want to avoid exposing fetching by ID in the public API,
|
89
92
|
# but it's needed for parity with the existing CLI. Therefore I am adding it
|
90
93
|
# as a hidden private API that can be used like: (`name="", _id=id`).
|
91
|
-
return
|
94
|
+
return _private_sdk.get_compute_config( # type: ignore
|
92
95
|
name=name or None, id=_id, include_archived=include_archived
|
93
96
|
)
|
94
97
|
|
@@ -108,7 +111,12 @@ _ARCHIVE_ARG_DOCSTRINGS = {"name": "Name of the compute config."}
|
|
108
111
|
doc_py_example=_ARCHIVE_EXAMPLE,
|
109
112
|
arg_docstrings=_ARCHIVE_ARG_DOCSTRINGS,
|
110
113
|
)
|
111
|
-
def archive(
|
114
|
+
def archive(
|
115
|
+
name: Optional[str],
|
116
|
+
*,
|
117
|
+
_id: Optional[str] = None,
|
118
|
+
_private_sdk: Optional[PrivateComputeConfigSDK] = None,
|
119
|
+
):
|
112
120
|
"""Archive a compute config and all of its versions.
|
113
121
|
|
114
122
|
The name can contain an optional version, e.g., 'name:version'.
|
@@ -119,4 +127,4 @@ def archive(name: str, *, _id: Optional[str] = None, _sdk: PrivateComputeConfigS
|
|
119
127
|
# NOTE(edoakes): I want to avoid exposing fetching by ID in the public API,
|
120
128
|
# but it's needed for parity with the existing CLI. Therefore I am adding it
|
121
129
|
# as a hidden private API that can be used like: (`name="", _id=id`).
|
122
|
-
return
|
130
|
+
return _private_sdk.archive_compute_config(name=name or None, id=_id) # type: ignore
|
@@ -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:
|
@@ -1411,7 +1411,7 @@ class CloudController(BaseController):
|
|
1411
1411
|
)
|
1412
1412
|
if enable_log_ingestion is not None:
|
1413
1413
|
self._update_customer_aggregated_logs_config(
|
1414
|
-
cloud_id=cloud_id, is_enabled=enable_log_ingestion,
|
1414
|
+
cloud_id=cloud_id, is_enabled=enable_log_ingestion, # type: ignore
|
1415
1415
|
)
|
1416
1416
|
self.log.info(
|
1417
1417
|
f"Successfully updated log ingestion configuration for cloud, "
|
@@ -1552,7 +1552,7 @@ class CloudController(BaseController):
|
|
1552
1552
|
cloud_resource=cloud_resource,
|
1553
1553
|
boto3_session=boto3_session,
|
1554
1554
|
region=cloud.region,
|
1555
|
-
cloud_id=cloud_id,
|
1555
|
+
cloud_id=cloud_id, # type: ignore
|
1556
1556
|
is_bring_your_own_resource=cloud.is_bring_your_own_resource,
|
1557
1557
|
is_private_network=cloud.is_private_cloud
|
1558
1558
|
if cloud.is_private_cloud
|
@@ -1575,7 +1575,7 @@ class CloudController(BaseController):
|
|
1575
1575
|
project_id=project_id,
|
1576
1576
|
host_project_id=host_project_id,
|
1577
1577
|
region=cloud.region,
|
1578
|
-
cloud_id=cloud_id,
|
1578
|
+
cloud_id=cloud_id, # type: ignore
|
1579
1579
|
yes=False,
|
1580
1580
|
strict=strict,
|
1581
1581
|
is_private_service_cloud=cloud.is_private_service_cloud,
|
@@ -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(
|
@@ -3539,8 +3539,8 @@ class CloudController(BaseController):
|
|
3539
3539
|
)
|
3540
3540
|
try:
|
3541
3541
|
self._edit_aws_cloud(
|
3542
|
-
cloud_id=cloud_id,
|
3543
|
-
cloud_name=cloud_name,
|
3542
|
+
cloud_id=cloud_id, # type: ignore
|
3543
|
+
cloud_name=cloud_name, # type: ignore
|
3544
3544
|
cloud=cloud,
|
3545
3545
|
cloud_resource=cloud_resource,
|
3546
3546
|
aws_s3_id=aws_s3_id,
|
@@ -3593,8 +3593,8 @@ class CloudController(BaseController):
|
|
3593
3593
|
)
|
3594
3594
|
try:
|
3595
3595
|
self._edit_gcp_cloud(
|
3596
|
-
cloud_id=cloud_id,
|
3597
|
-
cloud_name=cloud_name,
|
3596
|
+
cloud_id=cloud_id, # type: ignore
|
3597
|
+
cloud_name=cloud_name, # type: ignore
|
3598
3598
|
cloud=cloud,
|
3599
3599
|
cloud_resource=cloud_resource,
|
3600
3600
|
gcp_filestore_instance_id=gcp_filestore_instance_id,
|
@@ -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] = []
|
@@ -522,6 +522,7 @@ class ClusterController(BaseController):
|
|
522
522
|
api_client=self.api_client,
|
523
523
|
anyscale_api_client=self.anyscale_api_client,
|
524
524
|
)
|
525
|
+
assert project_id is not None
|
525
526
|
cluster_name = self._get_or_generate_cluster_name(project_id, cluster_name)
|
526
527
|
return project_id, cluster_name
|
527
528
|
|
@@ -80,7 +80,7 @@ class JobController(BaseController):
|
|
80
80
|
log: Optional[LogsLogger] = None,
|
81
81
|
initialize_auth_api_client: bool = True,
|
82
82
|
raise_structured_exception: bool = False,
|
83
|
-
auth_token: str = None,
|
83
|
+
auth_token: Optional[str] = None,
|
84
84
|
):
|
85
85
|
if log is None:
|
86
86
|
log = LogsLogger()
|
@@ -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"),
|
@@ -354,6 +354,7 @@ class ServiceController(BaseController):
|
|
354
354
|
)
|
355
355
|
|
356
356
|
else:
|
357
|
+
assert ray_serve_config is not None
|
357
358
|
ray_serve_config["runtime_env"] = override_runtime_env_config(
|
358
359
|
runtime_env=ray_serve_config.get("runtime_env"),
|
359
360
|
anyscale_api_client=self.sdk,
|