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.
Files changed (75) hide show
  1. anyscale/_private/anyscale_client/anyscale_client.py +4 -2
  2. anyscale/_private/anyscale_client/common.py +6 -4
  3. anyscale/_private/anyscale_client/fake_anyscale_client.py +16 -7
  4. anyscale/_private/docgen/__main__.py +4 -4
  5. anyscale/_private/docgen/generator.py +2 -2
  6. anyscale/_private/models/model_base.py +5 -2
  7. anyscale/_private/sdk/__init__.py +2 -2
  8. anyscale/_private/utils/progress_util.py +2 -2
  9. anyscale/_private/workload/workload_sdk.py +10 -7
  10. anyscale/aggregated_instance_usage/commands.py +6 -2
  11. anyscale/anyscale-cloud-setup.yaml +4 -0
  12. anyscale/client/README.md +8 -11
  13. anyscale/client/openapi_client/__init__.py +6 -8
  14. anyscale/client/openapi_client/api/default_api.py +292 -377
  15. anyscale/client/openapi_client/models/__init__.py +6 -8
  16. anyscale/client/openapi_client/models/alert_type.py +11 -2
  17. anyscale/client/openapi_client/models/create_job_queue_requests.py +3 -32
  18. anyscale/client/openapi_client/models/{product_autoscaler_flag.py → list_ray_sessions_response.py} +22 -23
  19. anyscale/client/openapi_client/models/{productautoscalerflag_response.py → listraysessionsresponse_response.py} +11 -11
  20. anyscale/client/openapi_client/models/metric.py +133 -3
  21. anyscale/client/openapi_client/models/ray_session.py +121 -0
  22. anyscale/client/openapi_client/models/task_exception_group_aggregate.py +28 -1
  23. anyscale/client/openapi_client/models/{taskexceptiongroupaggregate_list_response.py → task_exception_group_aggregate_response.py} +52 -25
  24. anyscale/client/openapi_client/models/task_function_name_group_aggregate.py +28 -1
  25. anyscale/client/openapi_client/models/{taskfunctionnamegroupaggregate_list_response.py → task_function_name_group_aggregate_response.py} +52 -25
  26. anyscale/client/openapi_client/models/task_job_group_aggregate.py +28 -1
  27. anyscale/client/openapi_client/models/{taskjobgroupaggregate_list_response.py → task_job_group_aggregate_response.py} +52 -25
  28. anyscale/client/openapi_client/models/task_table_row.py +19 -19
  29. anyscale/cloud/__init__.py +2 -2
  30. anyscale/cloud/_private/cloud_sdk.py +2 -2
  31. anyscale/cloud/commands.py +9 -6
  32. anyscale/cloud_resource.py +1 -1
  33. anyscale/cloud_utils.py +11 -6
  34. anyscale/cluster_compute.py +6 -5
  35. anyscale/cluster_env.py +10 -5
  36. anyscale/commands/login_commands.py +24 -3
  37. anyscale/commands/schedule_commands.py +2 -1
  38. anyscale/compute_config/_private/compute_config_sdk.py +1 -1
  39. anyscale/compute_config/commands.py +15 -7
  40. anyscale/connect_utils/prepare_cluster.py +14 -4
  41. anyscale/controllers/cloud_controller.py +9 -9
  42. anyscale/controllers/cloud_functional_verification_controller.py +4 -2
  43. anyscale/controllers/cluster_controller.py +1 -0
  44. anyscale/controllers/job_controller.py +1 -1
  45. anyscale/controllers/service_controller.py +2 -1
  46. anyscale/image/commands.py +6 -6
  47. anyscale/job/commands.py +12 -12
  48. anyscale/organization_invitation/commands.py +11 -7
  49. anyscale/project/__init__.py +2 -2
  50. anyscale/project/_private/project_sdk.py +2 -2
  51. anyscale/project/commands.py +3 -3
  52. anyscale/project_utils.py +5 -4
  53. anyscale/resource_quota/commands.py +18 -10
  54. anyscale/schedule/commands.py +12 -8
  55. anyscale/sdk/anyscale_client/sdk.py +5 -4
  56. anyscale/service/commands.py +17 -17
  57. anyscale/service_account/commands.py +12 -10
  58. anyscale/user/commands.py +5 -3
  59. anyscale/utils/connect_helpers.py +16 -3
  60. anyscale/utils/gcp_utils.py +25 -9
  61. anyscale/utils/runtime_env.py +3 -1
  62. anyscale/version.py +1 -1
  63. anyscale/workspace/__init__.py +10 -5
  64. anyscale/workspace/_private/workspace_sdk.py +9 -7
  65. anyscale/workspace/commands.py +25 -23
  66. {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/METADATA +1 -1
  67. {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/RECORD +72 -74
  68. anyscale/client/openapi_client/models/aviary_model_config_v2.py +0 -358
  69. anyscale/client/openapi_client/models/buffer_registration.py +0 -285
  70. anyscale/client/openapi_client/models/finish_ft_job_request_v2.py +0 -183
  71. {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/LICENSE +0 -0
  72. {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/NOTICE +0 -0
  73. {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/WHEEL +0 -0
  74. {anyscale-0.26.14.dist-info → anyscale-0.26.16.dist-info}/entry_points.txt +0 -0
  75. {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': 'dict(str, float)',
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
- 'session_name': 'str'
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
- 'session_name': 'session_name'
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, session_name=None, local_vars_configuration=None): # noqa: E501
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._session_name = None
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.session_name = session_name
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: dict(str, float)
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: dict(str, float)
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 session_name(self):
426
- """Gets the session_name of this TaskTableRow. # noqa: E501
425
+ def ray_session_name(self):
426
+ """Gets the ray_session_name of this TaskTableRow. # noqa: E501
427
427
 
428
428
 
429
- :return: The session_name of this TaskTableRow. # noqa: E501
429
+ :return: The ray_session_name of this TaskTableRow. # noqa: E501
430
430
  :rtype: str
431
431
  """
432
- return self._session_name
432
+ return self._ray_session_name
433
433
 
434
- @session_name.setter
435
- def session_name(self, session_name):
436
- """Sets the session_name of this TaskTableRow.
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 session_name: The session_name of this TaskTableRow. # noqa: E501
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 session_name is None: # noqa: E501
443
- raise ValueError("Invalid value for `session_name`, must not be `None`") # noqa: E501
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._session_name = session_name
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"""
@@ -38,14 +38,14 @@ class CloudSDK:
38
38
  )
39
39
  def add_collaborators(
40
40
  self, cloud: str, collaborators: List[CreateCloudCollaborator],
41
- ) -> str:
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
- return self._private_sdk.add_collaborators(cloud, collaborators)
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
- ) -> str:
19
+ ) -> None:
20
20
  cloud_id = self.client.get_cloud_id(cloud_name=cloud, compute_config_id=None)
21
21
 
22
- return self.client.add_cloud_collaborators(
22
+ self.client.add_cloud_collaborators(
23
23
  cloud_id=cloud_id,
24
24
  collaborators=[
25
25
  CreateCloudCollaboratorModel(
@@ -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, collaborators: List[CreateCloudCollaborator], *, _sdk: PrivateCloudSDK,
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 _sdk.add_collaborators(cloud, collaborators)
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
- _sdk: PrivateCloudSDK,
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 _sdk.get(id=id, name=name)
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(*, _sdk: PrivateCloudSDK,) -> Optional[Cloud]:
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 _sdk.get_default()
116
+ return _private_sdk.get_default() # type: ignore
@@ -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, CloudAnalyticsEventCloudResource] = {
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], anyscale_api_client: Optional[DefaultApi] = None
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(anyscale_api_client: Optional[DefaultApi] = None) -> List[Cloud]:
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
@@ -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, anyscale_api_client: Optional[DefaultApi] = None,
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, anyscale_api_client: Optional[DefaultApi] = None,
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
- def anyscale_login(no_expire: bool, expire_in_days: int) -> None:
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
- with contextlib.suppress(Exception):
56
- webbrowser.open(r.url)
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, *, name: Optional[str], _sdk: PrivateComputeConfigSDK,
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, _ = _sdk.create_compute_config(config, name=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
- _sdk: PrivateComputeConfigSDK,
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 _sdk.get_compute_config(
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(name: str, *, _id: Optional[str] = None, _sdk: PrivateComputeConfigSDK):
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 _sdk.archive_compute_config(name=name or None, id=_id)
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
- results = list_entities(
279
- self.anyscale_api_client.list_sessions, project_id, max=100
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. Do you want to continue?"
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
- "\n".join(confirmation_message), yes,
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,