anyscale 0.24.88__py3-none-any.whl → 0.25.5__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 (148) hide show
  1. anyscale/__init__.py +56 -0
  2. anyscale/_private/anyscale_client/anyscale_client.py +179 -28
  3. anyscale/_private/anyscale_client/common.py +109 -2
  4. anyscale/_private/anyscale_client/fake_anyscale_client.py +239 -1
  5. anyscale/_private/docgen/README.md +1 -1
  6. anyscale/_private/docgen/__main__.py +71 -21
  7. anyscale/_private/docgen/api.md +13 -20
  8. anyscale/_private/docgen/generator.py +3 -2
  9. anyscale/_private/docgen/models.md +4 -49
  10. anyscale/_private/workload/workload_config.py +21 -7
  11. anyscale/aggregated_instance_usage/__init__.py +1 -1
  12. anyscale/aggregated_instance_usage/commands.py +2 -4
  13. anyscale/aggregated_instance_usage/models.py +8 -8
  14. anyscale/client/README.md +25 -22
  15. anyscale/client/openapi_client/__init__.py +16 -14
  16. anyscale/client/openapi_client/api/default_api.py +1139 -959
  17. anyscale/client/openapi_client/models/__init__.py +16 -14
  18. anyscale/client/openapi_client/models/baseimagesenum.py +43 -1
  19. anyscale/client/openapi_client/models/{session_event_types.py → cloud_deployment_config.py} +35 -24
  20. anyscale/client/openapi_client/models/{platformfinetuningjob_response.py → clouddeploymentconfig_response.py} +11 -11
  21. anyscale/client/openapi_client/models/{log_level_types.py → cluster_event_source.py} +12 -7
  22. anyscale/client/openapi_client/models/{company_size.py → cluster_size.py} +10 -10
  23. anyscale/client/openapi_client/models/cluster_status_details.py +2 -1
  24. anyscale/client/openapi_client/models/{sessionevent_list_response.py → clusterevent_list_response.py} +15 -15
  25. anyscale/client/openapi_client/models/create_experimental_workspace.py +29 -1
  26. anyscale/client/openapi_client/models/create_notification_channel_record.py +29 -3
  27. anyscale/client/openapi_client/models/decorated_interactive_session.py +1 -57
  28. anyscale/client/openapi_client/models/decorated_job.py +1 -57
  29. anyscale/client/openapi_client/models/decorated_job_submission.py +1 -29
  30. anyscale/client/openapi_client/models/decorated_production_job.py +1 -29
  31. anyscale/client/openapi_client/models/decorated_session.py +1 -57
  32. anyscale/client/openapi_client/models/decorated_unified_job.py +1 -30
  33. anyscale/client/openapi_client/models/{resubmit_ft_job_request.py → describe_machine_pool_request.py} +21 -20
  34. anyscale/client/openapi_client/models/describe_machine_pool_response.py +123 -0
  35. anyscale/client/openapi_client/models/describemachinepoolresponse_response.py +121 -0
  36. anyscale/client/openapi_client/models/ha_jobs_sort_field.py +1 -2
  37. anyscale/client/openapi_client/models/internal_production_job.py +1 -29
  38. anyscale/client/openapi_client/models/jobs_sort_field.py +1 -2
  39. anyscale/client/openapi_client/models/machine_allocation_state.py +3 -1
  40. anyscale/client/openapi_client/models/machine_state_info.py +326 -0
  41. anyscale/client/openapi_client/models/{fine_tuning_job_status.py → notification_channel_slack_config.py} +34 -16
  42. anyscale/client/openapi_client/models/organization_marketing_questions.py +80 -54
  43. anyscale/client/openapi_client/models/request_state_info.py +210 -0
  44. anyscale/client/openapi_client/models/{platformfinetuningjob_list_response.py → scheduler_info.py} +43 -38
  45. anyscale/client/openapi_client/models/serve_deployment_fast_api_docs_status.py +123 -0
  46. anyscale/client/openapi_client/models/serve_deployment_state.py +2 -1
  47. anyscale/client/openapi_client/models/servedeploymentfastapidocsstatus_response.py +121 -0
  48. anyscale/client/openapi_client/models/sessions_sort_field.py +1 -2
  49. anyscale/client/openapi_client/models/supportedbaseimagesenum.py +43 -1
  50. anyscale/client/openapi_client/models/unified_job_sort_field.py +1 -2
  51. anyscale/client/openapi_client/models/update_cloud_collaborator.py +121 -0
  52. anyscale/client/openapi_client/models/usage_by_cluster.py +28 -1
  53. anyscale/client/openapi_client/models/usage_by_user.py +30 -3
  54. anyscale/client/openapi_client/models/workload_info.py +210 -0
  55. anyscale/cloud/__init__.py +83 -0
  56. anyscale/cloud/_private/cloud_sdk.py +25 -0
  57. anyscale/cloud/commands.py +45 -0
  58. anyscale/cloud/models.py +91 -0
  59. anyscale/cluster_compute.py +1 -1
  60. anyscale/commands/aggregated_instance_usage_commands.py +4 -4
  61. anyscale/commands/cloud_commands.py +87 -14
  62. anyscale/commands/command_examples.py +65 -0
  63. anyscale/commands/job_commands.py +15 -3
  64. anyscale/commands/machine_pool_commands.py +113 -1
  65. anyscale/commands/organization_invitation_commands.py +98 -0
  66. anyscale/commands/project_commands.py +52 -2
  67. anyscale/commands/resource_quota_commands.py +98 -11
  68. anyscale/commands/service_account_commands.py +65 -8
  69. anyscale/commands/service_commands.py +61 -1
  70. anyscale/commands/session_commands_hidden.py +5 -1
  71. anyscale/commands/user_commands.py +1 -1
  72. anyscale/commands/util.py +2 -2
  73. anyscale/commands/workspace_commands.py +1 -1
  74. anyscale/connect.py +1 -1
  75. anyscale/connect_utils/project.py +7 -4
  76. anyscale/controllers/cloud_controller.py +63 -30
  77. anyscale/controllers/cloud_functional_verification_controller.py +1 -1
  78. anyscale/controllers/cluster_controller.py +3 -11
  79. anyscale/controllers/compute_config_controller.py +1 -1
  80. anyscale/controllers/experimental_integrations_controller.py +1 -1
  81. anyscale/controllers/job_controller.py +8 -6
  82. anyscale/controllers/list_controller.py +2 -2
  83. anyscale/controllers/machine_pool_controller.py +12 -1
  84. anyscale/controllers/project_controller.py +4 -3
  85. anyscale/controllers/schedule_controller.py +1 -1
  86. anyscale/controllers/service_controller.py +1 -1
  87. anyscale/controllers/workspace_controller.py +1 -1
  88. anyscale/models/job_model.py +1 -1
  89. anyscale/organization_invitation/__init__.py +61 -0
  90. anyscale/organization_invitation/_private/organization_invitation_sdk.py +24 -0
  91. anyscale/organization_invitation/commands.py +84 -0
  92. anyscale/organization_invitation/models.py +45 -0
  93. anyscale/project/__init__.py +35 -0
  94. anyscale/project/_private/project_sdk.py +27 -0
  95. anyscale/project/commands.py +56 -0
  96. anyscale/project/models.py +91 -0
  97. anyscale/{project.py → project_utils.py} +3 -4
  98. anyscale/resource_quota/__init__.py +99 -0
  99. anyscale/resource_quota/_private/resource_quota_sdk.py +120 -0
  100. anyscale/resource_quota/commands.py +150 -0
  101. anyscale/resource_quota/models.py +303 -0
  102. anyscale/scripts.py +4 -0
  103. anyscale/sdk/anyscale_client/__init__.py +0 -5
  104. anyscale/sdk/anyscale_client/api/default_api.py +119 -150
  105. anyscale/sdk/anyscale_client/models/__init__.py +0 -5
  106. anyscale/sdk/anyscale_client/models/baseimagesenum.py +43 -1
  107. anyscale/sdk/anyscale_client/models/cluster_status_details.py +2 -1
  108. anyscale/sdk/anyscale_client/models/jobs_sort_field.py +1 -2
  109. anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +43 -1
  110. anyscale/sdk/anyscale_client/sdk.py +1 -1
  111. anyscale/service/__init__.py +21 -0
  112. anyscale/service/_private/service_sdk.py +13 -0
  113. anyscale/service/commands.py +35 -0
  114. anyscale/service_account/__init__.py +88 -0
  115. anyscale/service_account/_private/service_account_sdk.py +101 -0
  116. anyscale/service_account/commands.py +147 -0
  117. anyscale/service_account/models.py +66 -0
  118. anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
  119. anyscale/shared_anyscale_utils/utils/id_gen.py +2 -0
  120. anyscale/user/__init__.py +1 -1
  121. anyscale/user/commands.py +1 -1
  122. anyscale/user/models.py +25 -15
  123. anyscale/util.py +23 -0
  124. anyscale/utils/cloud_utils.py +1 -1
  125. anyscale/version.py +1 -1
  126. anyscale/workspace_utils.py +1 -1
  127. {anyscale-0.24.88.dist-info → anyscale-0.25.5.dist-info}/METADATA +1 -5
  128. {anyscale-0.24.88.dist-info → anyscale-0.25.5.dist-info}/RECORD +134 -119
  129. anyscale/client/openapi_client/models/create_fine_tuning_hyperparameters.py +0 -156
  130. anyscale/client/openapi_client/models/create_fine_tuning_job_product_request.py +0 -353
  131. anyscale/client/openapi_client/models/finish_ft_job_request.py +0 -204
  132. anyscale/client/openapi_client/models/platform_fine_tuning_job.py +0 -577
  133. anyscale/client/openapi_client/models/session_event.py +0 -267
  134. anyscale/client/openapi_client/models/session_event_cause.py +0 -150
  135. anyscale/controllers/resource_quota_controller.py +0 -183
  136. anyscale/controllers/service_account_controller.py +0 -168
  137. anyscale/sdk/anyscale_client/models/log_level_types.py +0 -100
  138. anyscale/sdk/anyscale_client/models/session_event.py +0 -267
  139. anyscale/sdk/anyscale_client/models/session_event_cause.py +0 -150
  140. anyscale/sdk/anyscale_client/models/session_event_types.py +0 -111
  141. anyscale/sdk/anyscale_client/models/sessionevent_list_response.py +0 -147
  142. anyscale/utils/imports/azure.py +0 -14
  143. /anyscale/{cloud.py → cloud_utils.py} +0 -0
  144. {anyscale-0.24.88.dist-info → anyscale-0.25.5.dist-info}/LICENSE +0 -0
  145. {anyscale-0.24.88.dist-info → anyscale-0.25.5.dist-info}/NOTICE +0 -0
  146. {anyscale-0.24.88.dist-info → anyscale-0.25.5.dist-info}/WHEEL +0 -0
  147. {anyscale-0.24.88.dist-info → anyscale-0.25.5.dist-info}/entry_points.txt +0 -0
  148. {anyscale-0.24.88.dist-info → anyscale-0.25.5.dist-info}/top_level.txt +0 -0
anyscale/__init__.py CHANGED
@@ -20,13 +20,18 @@ path.append(os.path.join(anyscale_dir, "sdk"))
20
20
  import anyscale
21
21
  from anyscale import (
22
22
  aggregated_instance_usage,
23
+ cloud,
23
24
  compute_config,
24
25
  image,
25
26
  integrations,
26
27
  job,
27
28
  llm,
29
+ organization_invitation,
30
+ project,
31
+ resource_quota,
28
32
  schedule,
29
33
  service,
34
+ service_account,
30
35
  user,
31
36
  )
32
37
  from anyscale._private.anyscale_client import AnyscaleClient, AnyscaleClientInterface
@@ -34,6 +39,7 @@ from anyscale._private.sdk.base_sdk import Timer
34
39
  from anyscale.aggregated_instance_usage import AggregatedInstanceUsageSDK
35
40
  from anyscale.authenticate import AuthenticationBlock
36
41
  from anyscale.cli_logger import BlockLogger
42
+ from anyscale.cloud import CloudSDK
37
43
  from anyscale.cluster import get_job_submission_client_cluster_info
38
44
  from anyscale.cluster_compute import get_cluster_compute_from_name
39
45
  from anyscale.compute_config import ComputeConfigSDK
@@ -41,9 +47,13 @@ from anyscale.connect import ClientBuilder
41
47
  from anyscale.image import ImageSDK
42
48
  from anyscale.job import JobSDK
43
49
  from anyscale.llm import LLMSDK
50
+ from anyscale.organization_invitation import OrganizationInvitationSDK
51
+ from anyscale.project import ProjectSDK
52
+ from anyscale.resource_quota import ResourceQuotaSDK
44
53
  from anyscale.schedule import ScheduleSDK
45
54
  from anyscale.sdk.anyscale_client.sdk import AnyscaleSDK
46
55
  from anyscale.service import ServiceSDK
56
+ from anyscale.service_account import ServiceAccountSDK
47
57
  from anyscale.user import UserSDK
48
58
  from anyscale.workspace import WorkspaceSDK
49
59
 
@@ -58,6 +68,10 @@ for attr, _ in inspect.getmembers(ClientBuilder, inspect.isfunction):
58
68
  if attr.startswith("_"):
59
69
  continue
60
70
 
71
+ # This is exposed in anyscale/cloud/__init__.py since anyscale.cloud is used as the SDK module too.
72
+ if attr == "cloud":
73
+ continue
74
+
61
75
  def _new_builder(attr: str) -> Any:
62
76
  target = getattr(ClientBuilder, attr)
63
77
 
@@ -107,9 +121,16 @@ class Anyscale:
107
121
  self._job_sdk = JobSDK(client=self._anyscale_client)
108
122
  self._service_sdk = ServiceSDK(client=self._anyscale_client)
109
123
  self._compute_config_sdk = ComputeConfigSDK(client=self._anyscale_client)
124
+ self._cloud_sdk = CloudSDK(client=self._anyscale_client)
110
125
  self._schedule_sdk = ScheduleSDK(client=self._anyscale_client)
111
126
  self._image_sdk = ImageSDK(client=self._anyscale_client)
112
127
  self._llm_sdk = LLMSDK(client=self._anyscale_client)
128
+ self._organization_invitation_sdk = OrganizationInvitationSDK(
129
+ client=self._anyscale_client
130
+ )
131
+ self._project_sdk = ProjectSDK(client=self._anyscale_client)
132
+ self._resource_quota_sdk = ResourceQuotaSDK(client=self._anyscale_client)
133
+ self._service_account_sdk = ServiceAccountSDK(client=self._anyscale_client)
113
134
  self._user_sdk = UserSDK(client=self._anyscale_client)
114
135
  self._workspace_sdk = WorkspaceSDK(client=self._anyscale_client)
115
136
 
@@ -131,13 +152,28 @@ class Anyscale:
131
152
  obj._compute_config_sdk = ComputeConfigSDK( # noqa: SLF001
132
153
  client=client, logger=logger, timer=timer
133
154
  )
155
+ obj._cloud_sdk = CloudSDK( # noqa: SLF001
156
+ client=client, logger=logger, timer=timer
157
+ )
134
158
  obj._schedule_sdk = ScheduleSDK( # noqa: SLF001
135
159
  client=client, logger=logger, timer=timer,
136
160
  )
137
161
  obj._image_sdk = ImageSDK(client=client, logger=logger) # noqa: SLF001
162
+ obj._organization_invitation_sdk = OrganizationInvitationSDK( # noqa: SLF001
163
+ client=client, logger=logger
164
+ )
165
+ obj._project_sdk = ProjectSDK( # noqa: SLF001
166
+ client=client, logger=logger, timer=timer
167
+ )
168
+ obj._service_account_sdk = ServiceAccountSDK( # noqa: SLF001
169
+ client=client, logger=logger, timer=timer
170
+ )
138
171
  obj._user_sdk = UserSDK( # noqa: SLF001
139
172
  client=client, logger=logger, timer=timer
140
173
  )
174
+ obj._resource_quota_sdk = ResourceQuotaSDK( # noqa: SLF001
175
+ client=client, logger=logger, timer=timer
176
+ )
141
177
  obj._workspace_sdk = WorkspaceSDK( # noqa: SLF001
142
178
  client=client, logger=logger, timer=timer,
143
179
  )
@@ -159,6 +195,10 @@ class Anyscale:
159
195
  def compute_config(self) -> ComputeConfigSDK: # noqa: F811
160
196
  return self._compute_config_sdk
161
197
 
198
+ @property
199
+ def cloud(self) -> CloudSDK: # noqa: F811
200
+ return self._cloud_sdk
201
+
162
202
  @property
163
203
  def schedule(self) -> ScheduleSDK: # noqa: F811
164
204
  return self._schedule_sdk
@@ -171,6 +211,22 @@ class Anyscale:
171
211
  def llm(self) -> LLMSDK: # noqa: F811
172
212
  return self._llm_sdk
173
213
 
214
+ @property
215
+ def organization_invitation(self) -> OrganizationInvitationSDK: # noqa: F811
216
+ return self._organization_invitation_sdk
217
+
218
+ @property
219
+ def project(self) -> ProjectSDK: # noqa: F811
220
+ return self._project_sdk
221
+
222
+ @property
223
+ def resource_quota(self) -> ResourceQuotaSDK: # noqa: F811
224
+ return self._resource_quota_sdk
225
+
226
+ @property
227
+ def service_account(self) -> ServiceAccountSDK: # noqa: F811
228
+ return self._service_account_sdk
229
+
174
230
  @property
175
231
  def user(self) -> UserSDK: # noqa: F811
176
232
  return self._user_sdk
@@ -36,6 +36,8 @@ from anyscale.client.openapi_client.api.default_api import DefaultApi as Interna
36
36
  from anyscale.client.openapi_client.models import (
37
37
  AdminCreatedUser,
38
38
  AdminCreateUser,
39
+ AnyscaleServiceAccount,
40
+ ApiKeyParameters,
39
41
  ArchiveStatus,
40
42
  Cloud,
41
43
  CloudDataBucketAccessMode,
@@ -47,10 +49,14 @@ from anyscale.client.openapi_client.models import (
47
49
  ComputeTemplate,
48
50
  ComputeTemplateConfig,
49
51
  ComputeTemplateQuery,
52
+ CreateCloudCollaborator,
50
53
  CreateComputeTemplate,
51
54
  CreateDataset,
52
55
  CreateExperimentalWorkspace,
53
56
  CreateInternalProductionJob,
57
+ CreateOrganizationInvitation,
58
+ CreateResourceQuota,
59
+ CreateUserProjectCollaborator,
54
60
  Dataset as InternalDataset,
55
61
  DatasetUpload,
56
62
  DecoratedComputeTemplate,
@@ -60,6 +66,12 @@ from anyscale.client.openapi_client.models import (
60
66
  FineTunedModel,
61
67
  FinetunedmodelListResponse,
62
68
  InternalProductionJob,
69
+ ListResourceQuotasQuery,
70
+ OrganizationCollaborator,
71
+ OrganizationInvitation,
72
+ ResourceQuota,
73
+ ResourceQuotaStatus,
74
+ ServerSessionToken,
63
75
  SessionSshKey,
64
76
  StartSessionOptions,
65
77
  StopSessionOptions,
@@ -544,6 +556,14 @@ class AnyscaleClient(AnyscaleClientInterface):
544
556
 
545
557
  raise e from None
546
558
 
559
+ @handle_api_exceptions
560
+ def add_cloud_collaborators(
561
+ self, cloud_id: str, collaborators: List[CreateCloudCollaborator]
562
+ ) -> None:
563
+ self._internal_api_client.batch_create_cloud_collaborators_api_v2_clouds_cloud_id_collaborators_users_batch_create_post(
564
+ cloud_id, collaborators
565
+ )
566
+
547
567
  @handle_api_exceptions
548
568
  def create_compute_config(
549
569
  self, config: ComputeTemplateConfig, *, name: Optional[str] = None
@@ -986,6 +1006,14 @@ class AnyscaleClient(AnyscaleClientInterface):
986
1006
  project_id
987
1007
  ).result
988
1008
 
1009
+ @handle_api_exceptions
1010
+ def add_project_collaborators(
1011
+ self, project_id: str, collaborators: List[CreateUserProjectCollaborator]
1012
+ ) -> None:
1013
+ self._internal_api_client.batch_create_project_collaborators_api_v2_projects_project_id_collaborators_users_batch_create_post(
1014
+ project_id, collaborators
1015
+ )
1016
+
989
1017
  @handle_api_exceptions
990
1018
  def get_job(
991
1019
  self,
@@ -1067,6 +1095,11 @@ class AnyscaleClient(AnyscaleClientInterface):
1067
1095
  result: ServiceModel = self._external_api_client.terminate_service(service_id)
1068
1096
  return result
1069
1097
 
1098
+ @handle_api_exceptions
1099
+ def archive_service(self, service_id: str) -> ServiceModel:
1100
+ result: ServiceModel = self._external_api_client.archive_service(service_id)
1101
+ return result
1102
+
1070
1103
  @handle_api_exceptions
1071
1104
  def submit_job(self, model: CreateInternalProductionJob) -> InternalProductionJob:
1072
1105
  job: InternalProductionJob = self._internal_api_client.create_job_api_v2_decorated_ha_jobs_create_post(
@@ -1122,39 +1155,26 @@ class AnyscaleClient(AnyscaleClientInterface):
1122
1155
  # If the presigned URL scheme is SMART_OPEN, upload to cloud storage using the provided bucket name, path, & environment, and the smart_open library.
1123
1156
  bucket_name = info.bucket_name
1124
1157
  bucket_path = info.bucket_path
1125
- file_uri = info.file_uri
1126
1158
 
1127
- if file_uri and file_uri.startswith("azure"):
1128
-
1129
- from anyscale.utils.imports.azure import (
1130
- try_import_azure_storage_blob_BlobServiceClient,
1131
- )
1132
-
1133
- # Smartopen needs transport_params to be passed in for Azure.
1134
- blob_service_client = (
1135
- try_import_azure_storage_blob_BlobServiceClient()
1136
- )
1137
-
1138
- transport_params = {
1139
- "client": blob_service_client.from_connection_string(info.url),
1140
- }
1141
- with smart_open.open(
1142
- f"{file_uri}", "wb", transport_params=transport_params,
1143
- ) as fout:
1144
- fout.write(zip_file_bytes)
1145
- else:
1146
- env_vars: Dict[str, str] = {
1147
- "AWS_ENDPOINT_URL": info.url,
1148
- }
1149
- with set_env(**env_vars), smart_open.open(
1150
- f"{bucket_name}/{bucket_path}", "wb",
1151
- ) as fout:
1152
- fout.write(zip_file_bytes)
1159
+ env_vars: Dict[str, str] = {
1160
+ "AWS_ENDPOINT_URL": info.url,
1161
+ }
1162
+ with set_env(**env_vars), smart_open.open(
1163
+ f"{bucket_name}/{bucket_path}", "wb",
1164
+ ) as fout:
1165
+ fout.write(zip_file_bytes)
1153
1166
 
1154
1167
  else:
1155
1168
  # Default to HTTP PUT.
1156
1169
  internal_logger.debug(f"Uploading file '{file_name}' to cloud storage.")
1157
- requests.put(info.url, data=zip_file_bytes).raise_for_status()
1170
+ headers = (
1171
+ {"x-ms-blob-type": "BlockBlob"}
1172
+ if info.file_uri.startswith("azure")
1173
+ else None
1174
+ )
1175
+ requests.put(
1176
+ info.url, data=zip_file_bytes, headers=headers
1177
+ ).raise_for_status()
1158
1178
 
1159
1179
  return info.file_uri
1160
1180
 
@@ -1848,6 +1868,20 @@ class AnyscaleClient(AnyscaleClientInterface):
1848
1868
 
1849
1869
  return filepath
1850
1870
 
1871
+ @handle_api_exceptions
1872
+ def create_api_key(
1873
+ self, duration: float, user_id: Optional[str]
1874
+ ) -> ServerSessionToken:
1875
+ return self._internal_api_client.create_api_key_api_v2_users_create_api_key_post(
1876
+ ApiKeyParameters(user_id=user_id, duration=duration)
1877
+ ).result
1878
+
1879
+ @handle_api_exceptions
1880
+ def rotate_api_key(self, user_id: str) -> None:
1881
+ self._internal_api_client.rotate_api_key_for_user_api_v2_organization_collaborators_rotate_api_key_for_user_user_id_post(
1882
+ user_id
1883
+ )
1884
+
1851
1885
  @handle_api_exceptions
1852
1886
  def admin_batch_create_users(
1853
1887
  self, admin_create_users: List[AdminCreateUser]
@@ -1855,3 +1889,120 @@ class AnyscaleClient(AnyscaleClientInterface):
1855
1889
  return self._internal_api_client.admin_batch_create_users_api_v2_users_admin_batch_create_post(
1856
1890
  admin_create_users
1857
1891
  ).results
1892
+
1893
+ @handle_api_exceptions
1894
+ def create_organization_invitations(
1895
+ self, emails: List[str]
1896
+ ) -> Tuple[List[str], List[str]]:
1897
+ results = self._internal_api_client.batch_create_invitations_api_v2_organization_invitations_batch_create_post(
1898
+ [CreateOrganizationInvitation(email=email) for email in emails]
1899
+ ).results
1900
+
1901
+ success_emails = []
1902
+ error_messages = []
1903
+
1904
+ for idx, result in enumerate(results):
1905
+ if result.data:
1906
+ success_emails.append(emails[idx])
1907
+ else:
1908
+ error_messages.append(result.error.detail)
1909
+
1910
+ return success_emails, error_messages
1911
+
1912
+ @handle_api_exceptions
1913
+ def list_organization_invitations(self) -> List[OrganizationInvitation]:
1914
+ results = (
1915
+ self._internal_api_client.list_invitations_api_v2_organization_invitations_get().results
1916
+ )
1917
+
1918
+ return results
1919
+
1920
+ @handle_api_exceptions
1921
+ def delete_organization_invitation(self, email: str) -> OrganizationInvitation:
1922
+ invitation = self._internal_api_client.list_invitations_api_v2_organization_invitations_get(
1923
+ email=email
1924
+ ).results
1925
+
1926
+ if len(invitation) == 0:
1927
+ raise ValueError(f"Invitation for email '{email}' not found.")
1928
+ elif len(invitation) > 1:
1929
+ raise ValueError(
1930
+ f"Multiple invitations found for email '{email}'. Please contact Anyscale support."
1931
+ )
1932
+
1933
+ invitation_id = invitation[0].id
1934
+
1935
+ return self._internal_api_client.invalidate_invitation_api_v2_organization_invitations_invitation_id_invalidate_post(
1936
+ invitation_id
1937
+ ).result
1938
+
1939
+ @handle_api_exceptions
1940
+ def get_organization_collaborators(
1941
+ self,
1942
+ email: Optional[str] = None,
1943
+ name: Optional[str] = None,
1944
+ is_service_account: Optional[bool] = None,
1945
+ ) -> List[OrganizationCollaborator]:
1946
+ results = self._internal_api_client.list_organization_collaborators_api_v2_organization_collaborators_get(
1947
+ email=email, name=name, is_service_account=is_service_account
1948
+ ).results
1949
+
1950
+ return results
1951
+
1952
+ @handle_api_exceptions
1953
+ def delete_organization_collaborator(self, identity_id: str) -> None:
1954
+ self._internal_api_client.remove_organization_collaborator_api_v2_organization_collaborators_identity_id_delete(
1955
+ identity_id
1956
+ )
1957
+
1958
+ @handle_api_exceptions
1959
+ def create_service_account(self, name: str) -> AnyscaleServiceAccount:
1960
+ return self._internal_api_client.create_service_account_api_v2_users_service_accounts_post(
1961
+ name
1962
+ ).result
1963
+
1964
+ @handle_api_exceptions
1965
+ def create_resource_quota(
1966
+ self, create_resource_quota: CreateResourceQuota
1967
+ ) -> ResourceQuota:
1968
+ return self._internal_api_client.create_resource_quota_api_v2_resource_quotas_post(
1969
+ create_resource_quota
1970
+ ).result
1971
+
1972
+ @handle_api_exceptions
1973
+ def list_resource_quotas(
1974
+ self,
1975
+ name: Optional[str] = None,
1976
+ cloud_id: Optional[str] = None,
1977
+ creator_id: Optional[str] = None,
1978
+ is_enabled: Optional[bool] = None,
1979
+ max_items: int = 20,
1980
+ ) -> List[ResourceQuota]:
1981
+
1982
+ query = ListResourceQuotasQuery(
1983
+ name=TextQuery(equals=name) if name else None,
1984
+ cloud_id=cloud_id,
1985
+ creator_id=creator_id,
1986
+ is_enabled=is_enabled,
1987
+ paging=PageQuery(count=max_items),
1988
+ )
1989
+
1990
+ resource_quotas = self._internal_api_client.search_resource_quotas_api_v2_resource_quotas_search_post(
1991
+ query
1992
+ ).results
1993
+
1994
+ return resource_quotas
1995
+
1996
+ @handle_api_exceptions
1997
+ def delete_resource_quota(self, resource_quota_id: str) -> None:
1998
+ self._internal_api_client.delete_resource_quota_api_v2_resource_quotas_resource_quota_id_delete(
1999
+ resource_quota_id
2000
+ )
2001
+
2002
+ @handle_api_exceptions
2003
+ def set_resource_quota_status(
2004
+ self, resource_quota_id: str, is_enabled: bool
2005
+ ) -> None:
2006
+ self._internal_api_client.set_resource_quota_status_api_v2_resource_quotas_resource_quota_id_status_patch(
2007
+ resource_quota_id, ResourceQuotaStatus(is_enabled=is_enabled)
2008
+ ).result
@@ -6,15 +6,23 @@ from anyscale._private.models.image_uri import ImageURI
6
6
  from anyscale.client.openapi_client.models import (
7
7
  AdminCreatedUser,
8
8
  AdminCreateUser,
9
+ AnyscaleServiceAccount,
9
10
  Cloud,
10
11
  ComputeTemplateConfig,
12
+ CreateCloudCollaborator,
11
13
  CreateExperimentalWorkspace,
12
14
  CreateInternalProductionJob,
15
+ CreateResourceQuota,
16
+ CreateUserProjectCollaborator,
13
17
  DecoratedComputeTemplate,
14
18
  DeletedPlatformFineTunedModel,
15
19
  FineTunedModel,
16
20
  InternalProductionJob,
21
+ OrganizationCollaborator,
22
+ OrganizationInvitation,
17
23
  Project,
24
+ ResourceQuota,
25
+ ServerSessionToken,
18
26
  WorkspaceDataplaneProxiedArtifacts,
19
27
  )
20
28
  from anyscale.client.openapi_client.models.create_schedule import CreateSchedule
@@ -41,7 +49,7 @@ from anyscale.utils.workspace_notification import WorkspaceNotification
41
49
  # Maybe just make it part of the release process to update it, or fetch the
42
50
  # default builds and get the latest one. The best thing to do is probably
43
51
  # to populate this in the backend.
44
- DEFAULT_RAY_VERSION = "2.40.0" # RAY_RELEASE_UPDATE: update to latest version.
52
+ DEFAULT_RAY_VERSION = "2.41.0" # RAY_RELEASE_UPDATE: update to latest version.
45
53
  DEFAULT_PYTHON_VERSION = "py311"
46
54
  RUNTIME_ENV_PACKAGE_FORMAT = "pkg_{content_hash}.zip"
47
55
 
@@ -142,6 +150,13 @@ class AnyscaleClientInterface(ABC):
142
150
  """
143
151
  raise NotImplementedError
144
152
 
153
+ @abstractmethod
154
+ def add_cloud_collaborators(
155
+ self, cloud_id: str, collaborators: List[CreateCloudCollaborator]
156
+ ) -> None:
157
+ """Batch add collaborators to a cloud."""
158
+ raise NotImplementedError
159
+
145
160
  @abstractmethod
146
161
  def create_compute_config(
147
162
  self, config: ComputeTemplateConfig, *, name: Optional[str] = None
@@ -285,6 +300,13 @@ class AnyscaleClientInterface(ABC):
285
300
  """
286
301
  raise NotImplementedError
287
302
 
303
+ @abstractmethod
304
+ def add_project_collaborators(
305
+ self, project_id: str, collaborators: List[CreateUserProjectCollaborator]
306
+ ) -> None:
307
+ """Batch add collaborators to a project."""
308
+ raise NotImplementedError
309
+
288
310
  @abstractmethod
289
311
  def get_job(
290
312
  self,
@@ -331,6 +353,11 @@ class AnyscaleClientInterface(ABC):
331
353
  """Mark the service to be terminated asynchronously."""
332
354
  raise NotImplementedError
333
355
 
356
+ @abstractmethod
357
+ def archive_service(self, service_id: str):
358
+ """Mark the service to be archived asynchronously."""
359
+ raise NotImplementedError
360
+
334
361
  @abstractmethod
335
362
  def submit_job(self, model: CreateInternalProductionJob) -> InternalProductionJob:
336
363
  """Submit the job to run."""
@@ -594,9 +621,89 @@ class AnyscaleClientInterface(ABC):
594
621
  """Download the aggregated instance usage csv."""
595
622
  raise NotImplementedError
596
623
 
624
+ @abstractmethod
625
+ def create_api_key(
626
+ self, duration: float, user_id: Optional[str]
627
+ ) -> ServerSessionToken:
628
+ """Create a new API key."""
629
+ raise NotImplementedError
630
+
631
+ @abstractmethod
632
+ def rotate_api_key(self, user_id: str) -> None:
633
+ """Rotate the API key for user."""
634
+ raise NotImplementedError
635
+
597
636
  @abstractmethod
598
637
  def admin_batch_create_users(
599
638
  self, admin_create_users: List[AdminCreateUser]
600
639
  ) -> List[AdminCreatedUser]:
601
- """Batch create users without email verification as an admin."""
640
+ """Batch create, as an admin, users without email verification."""
641
+ raise NotImplementedError
642
+
643
+ @abstractmethod
644
+ def create_organization_invitations(
645
+ self, emails: List[str]
646
+ ) -> Tuple[List[str], List[str]]:
647
+ """Create organization invitations."""
648
+ raise NotImplementedError
649
+
650
+ @abstractmethod
651
+ def list_organization_invitations(self) -> List[OrganizationInvitation]:
652
+ """List organization invitations."""
653
+ raise NotImplementedError
654
+
655
+ @abstractmethod
656
+ def delete_organization_invitation(self, email: str) -> OrganizationInvitation:
657
+ """Delete organization invitation."""
658
+ raise NotImplementedError
659
+
660
+ @abstractmethod
661
+ def get_organization_collaborators(
662
+ self,
663
+ email: Optional[str] = None,
664
+ name: Optional[str] = None,
665
+ is_service_account: Optional[bool] = None,
666
+ ) -> List[OrganizationCollaborator]:
667
+ """Get organization collaborators."""
668
+ raise NotImplementedError
669
+
670
+ @abstractmethod
671
+ def delete_organization_collaborator(self, identity_id: str) -> None:
672
+ """Delete organization collaborator."""
673
+ raise NotImplementedError
674
+
675
+ @abstractmethod
676
+ def create_service_account(self, name: str) -> AnyscaleServiceAccount:
677
+ """Create a service account."""
678
+ raise NotImplementedError
679
+
680
+ @abstractmethod
681
+ def create_resource_quota(
682
+ self, create_resource_quota: CreateResourceQuota
683
+ ) -> ResourceQuota:
684
+ """Create a resource quota."""
685
+ raise NotImplementedError
686
+
687
+ @abstractmethod
688
+ def list_resource_quotas(
689
+ self,
690
+ name: Optional[str] = None,
691
+ cloud_id: Optional[str] = None,
692
+ creator_id: Optional[str] = None,
693
+ is_enabled: Optional[bool] = None,
694
+ max_items: int = 20,
695
+ ) -> List[ResourceQuota]:
696
+ """List resource quotas."""
697
+ raise NotImplementedError
698
+
699
+ @abstractmethod
700
+ def delete_resource_quota(self, resource_quota_id: str) -> None:
701
+ """Delete a resource quota."""
702
+ raise NotImplementedError
703
+
704
+ @abstractmethod
705
+ def set_resource_quota_status(
706
+ self, resource_quota_id: str, is_enabled: bool
707
+ ) -> None:
708
+ """Set the status of a resource quota."""
602
709
  raise NotImplementedError