anyscale 0.26.52__py3-none-any.whl → 0.26.53__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 (62) hide show
  1. anyscale/_private/anyscale_client/anyscale_client.py +26 -26
  2. anyscale/_private/anyscale_client/common.py +5 -5
  3. anyscale/_private/anyscale_client/fake_anyscale_client.py +6 -6
  4. anyscale/_private/docgen/__main__.py +8 -8
  5. anyscale/_private/docgen/generator.py +48 -10
  6. anyscale/_private/docgen/models.md +2 -2
  7. anyscale/_private/sdk/__init__.py +124 -1
  8. anyscale/_private/workload/workload_config.py +4 -6
  9. anyscale/_private/workload/workload_sdk.py +9 -11
  10. anyscale/client/README.md +12 -13
  11. anyscale/client/openapi_client/__init__.py +3 -4
  12. anyscale/client/openapi_client/api/default_api.py +272 -325
  13. anyscale/client/openapi_client/models/__init__.py +3 -4
  14. anyscale/client/openapi_client/models/aws_config.py +2 -2
  15. anyscale/client/openapi_client/models/baseimagesenum.py +76 -1
  16. anyscale/client/openapi_client/models/cloud_data_bucket_presigned_url_request.py +31 -3
  17. anyscale/client/openapi_client/models/cloud_deployment.py +37 -36
  18. anyscale/client/openapi_client/models/create_resource_notification.py +31 -3
  19. anyscale/client/openapi_client/models/{decorated_cloud_deployment.py → decorated_cloud_resource.py} +124 -96
  20. anyscale/client/openapi_client/models/{clouddeployment_list_response.py → decoratedcloudresource_list_response.py} +15 -15
  21. anyscale/client/openapi_client/models/{clouddeployment_response.py → decoratedcloudresource_response.py} +11 -11
  22. anyscale/client/openapi_client/models/file_storage.py +4 -4
  23. anyscale/client/openapi_client/models/gcp_config.py +2 -2
  24. anyscale/client/openapi_client/models/ha_job_error_types.py +9 -2
  25. anyscale/client/openapi_client/models/object_storage.py +2 -2
  26. anyscale/client/openapi_client/models/resource_alert_event_type.py +2 -1
  27. anyscale/client/openapi_client/models/resource_notification.py +29 -1
  28. anyscale/client/openapi_client/models/supportedbaseimagesenum.py +76 -1
  29. anyscale/client/openapi_client/models/workload_info.py +31 -3
  30. anyscale/client/openapi_client/models/workload_state_info.py +29 -1
  31. anyscale/cloud/models.py +39 -42
  32. anyscale/commands/cloud_commands.py +25 -23
  33. anyscale/commands/command_examples.py +10 -10
  34. anyscale/commands/exec_commands.py +12 -1
  35. anyscale/commands/list_commands.py +42 -12
  36. anyscale/commands/project_commands.py +23 -10
  37. anyscale/commands/schedule_commands.py +22 -11
  38. anyscale/commands/service_commands.py +11 -6
  39. anyscale/commands/util.py +94 -1
  40. anyscale/commands/workspace_commands.py +92 -38
  41. anyscale/compute_config/__init__.py +1 -1
  42. anyscale/compute_config/_private/compute_config_sdk.py +8 -11
  43. anyscale/compute_config/commands.py +3 -3
  44. anyscale/compute_config/models.py +30 -30
  45. anyscale/controllers/cloud_controller.py +306 -300
  46. anyscale/controllers/kubernetes_verifier.py +1 -1
  47. anyscale/job/_private/job_sdk.py +12 -12
  48. anyscale/job/models.py +1 -1
  49. anyscale/sdk/anyscale_client/models/baseimagesenum.py +76 -1
  50. anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +76 -1
  51. anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
  52. anyscale/version.py +1 -1
  53. anyscale/workspace/commands.py +114 -23
  54. anyscale/workspace/models.py +3 -5
  55. {anyscale-0.26.52.dist-info → anyscale-0.26.53.dist-info}/METADATA +1 -1
  56. {anyscale-0.26.52.dist-info → anyscale-0.26.53.dist-info}/RECORD +61 -62
  57. anyscale/client/openapi_client/models/decoratedclouddeployment_response.py +0 -121
  58. {anyscale-0.26.52.dist-info → anyscale-0.26.53.dist-info}/WHEEL +0 -0
  59. {anyscale-0.26.52.dist-info → anyscale-0.26.53.dist-info}/entry_points.txt +0 -0
  60. {anyscale-0.26.52.dist-info → anyscale-0.26.53.dist-info}/licenses/LICENSE +0 -0
  61. {anyscale-0.26.52.dist-info → anyscale-0.26.53.dist-info}/licenses/NOTICE +0 -0
  62. {anyscale-0.26.52.dist-info → anyscale-0.26.53.dist-info}/top_level.txt +0 -0
@@ -1292,7 +1292,7 @@ class AnyscaleClient(AnyscaleClientInterface):
1292
1292
  def _upload_local_runtime_env(
1293
1293
  self,
1294
1294
  cloud_id: str,
1295
- cloud_deployment_id: Optional[str],
1295
+ cloud_resource_id: Optional[str],
1296
1296
  zip_file_bytes: bytes,
1297
1297
  content_hash: str,
1298
1298
  overwrite_existing_file: bool,
@@ -1302,7 +1302,7 @@ class AnyscaleClient(AnyscaleClientInterface):
1302
1302
  file_type=CloudDataBucketFileType.RUNTIME_ENV_PACKAGES,
1303
1303
  file_name=file_name,
1304
1304
  access_mode=CloudDataBucketAccessMode.WRITE,
1305
- cloud_deployment_id=cloud_deployment_id,
1305
+ cloud_resource_id=cloud_resource_id,
1306
1306
  )
1307
1307
  info: CloudDataBucketPresignedUrlResponse = self._internal_api_client.generate_cloud_data_bucket_presigned_url_api_v2_clouds_cloud_id_generate_cloud_data_bucket_presigned_url_post(
1308
1308
  cloud_id, request
@@ -1355,27 +1355,27 @@ class AnyscaleClient(AnyscaleClientInterface):
1355
1355
  cloud_id: str,
1356
1356
  excludes: Optional[List[str]] = None,
1357
1357
  overwrite_existing_file: bool = OVERWRITE_EXISTING_CLOUD_STORAGE_FILES,
1358
- cloud_deployment: Optional[str] = None,
1358
+ cloud_resource_name: Optional[str] = None,
1359
1359
  ) -> str:
1360
1360
  if not pathlib.Path(local_dir).is_dir():
1361
1361
  raise RuntimeError(f"Path '{local_dir}' is not a valid directory.")
1362
1362
 
1363
- cloud_deployment_id = None
1364
- if cloud_deployment is not None:
1365
- cloud_deployments = self._internal_api_client.get_cloud_deployments_api_v2_clouds_cloud_id_deployments_get(
1363
+ cloud_resource_id = None
1364
+ if cloud_resource_name is not None:
1365
+ cloud_resources = self._internal_api_client.get_cloud_resources_api_v2_clouds_cloud_id_resources_get(
1366
1366
  cloud_id=cloud_id,
1367
1367
  ).results
1368
- cloud_deployment_id = next(
1368
+ cloud_resource_id = next(
1369
1369
  (
1370
- deployment.cloud_deployment_id
1371
- for deployment in cloud_deployments
1372
- if deployment.name == cloud_deployment
1370
+ cloud_resource.cloud_resource_id
1371
+ for cloud_resource in cloud_resources
1372
+ if cloud_resource.name == cloud_resource_name
1373
1373
  ),
1374
1374
  None,
1375
1375
  )
1376
- if cloud_deployment_id is None:
1376
+ if cloud_resource_id is None:
1377
1377
  raise ValueError(
1378
- f"Cloud deployment '{cloud_deployment}' not found in cloud '{cloud_id}'"
1378
+ f"Cloud resource '{cloud_resource_name}' not found in cloud '{cloud_id}'"
1379
1379
  )
1380
1380
 
1381
1381
  with zip_local_dir(local_dir, excludes=excludes) as (
@@ -1385,31 +1385,31 @@ class AnyscaleClient(AnyscaleClientInterface):
1385
1385
  ):
1386
1386
  info = self._upload_local_runtime_env(
1387
1387
  cloud_id=cloud_id,
1388
- cloud_deployment_id=cloud_deployment_id,
1388
+ cloud_resource_id=cloud_resource_id,
1389
1389
  zip_file_bytes=zip_file_bytes,
1390
1390
  content_hash=content_hash,
1391
1391
  overwrite_existing_file=overwrite_existing_file,
1392
1392
  )
1393
1393
  return info.file_uri
1394
1394
 
1395
- def upload_local_dir_to_cloud_storage_multi_deployment(
1395
+ def upload_local_dir_to_cloud_storage_multi_cloud_resource(
1396
1396
  self,
1397
1397
  local_dir: str,
1398
1398
  *,
1399
1399
  cloud_id: str,
1400
- cloud_deployments: List[Optional[str]],
1400
+ cloud_resource_names: List[Optional[str]],
1401
1401
  excludes: Optional[List[str]] = None,
1402
1402
  overwrite_existing_file: bool = False,
1403
1403
  ) -> str:
1404
1404
  if not pathlib.Path(local_dir).is_dir():
1405
1405
  raise RuntimeError(f"Path '{local_dir}' is not a valid directory.")
1406
1406
 
1407
- all_cloud_deployments = self._internal_api_client.get_cloud_deployments_api_v2_clouds_cloud_id_deployments_get(
1407
+ all_cloud_resources = self._internal_api_client.get_cloud_resources_api_v2_clouds_cloud_id_resources_get(
1408
1408
  cloud_id=cloud_id,
1409
1409
  ).results
1410
- cloud_deployment_ids = {
1411
- deployment.name: deployment.cloud_deployment_id
1412
- for deployment in all_cloud_deployments
1410
+ cloud_resource_names_to_ids = {
1411
+ cloud_resource.name: cloud_resource.cloud_resource_id
1412
+ for cloud_resource in all_cloud_resources
1413
1413
  }
1414
1414
 
1415
1415
  bucket_paths = set()
@@ -1419,19 +1419,19 @@ class AnyscaleClient(AnyscaleClientInterface):
1419
1419
  zip_file_bytes,
1420
1420
  content_hash,
1421
1421
  ):
1422
- for cloud_deployment in cloud_deployments:
1423
- if cloud_deployment is not None:
1424
- if cloud_deployment not in cloud_deployment_ids:
1422
+ for cloud_resource_name in cloud_resource_names:
1423
+ if cloud_resource_name is not None:
1424
+ if cloud_resource_name not in cloud_resource_names_to_ids:
1425
1425
  raise ValueError(
1426
- f"Cloud deployment '{cloud_deployment}' not found in cloud '{cloud_id}'"
1426
+ f"Cloud resource '{cloud_resource_name}' not found in cloud '{cloud_id}'"
1427
1427
  )
1428
- cloud_deployment_id = cloud_deployment_ids[cloud_deployment]
1428
+ cloud_resource_id = cloud_resource_names_to_ids[cloud_resource_name]
1429
1429
  else:
1430
- cloud_deployment_id = None
1430
+ cloud_resource_id = None
1431
1431
 
1432
1432
  info = self._upload_local_runtime_env(
1433
1433
  cloud_id=cloud_id,
1434
- cloud_deployment_id=cloud_deployment_id,
1434
+ cloud_resource_id=cloud_resource_id,
1435
1435
  zip_file_bytes=zip_file_bytes,
1436
1436
  content_hash=content_hash,
1437
1437
  overwrite_existing_file=overwrite_existing_file,
@@ -57,7 +57,7 @@ from anyscale.utils.workspace_notification import WorkspaceNotification
57
57
  # Maybe just make it part of the release process to update it, or fetch the
58
58
  # default builds and get the latest one. The best thing to do is probably
59
59
  # to populate this in the backend.
60
- DEFAULT_RAY_VERSION = "2.49.0" # RAY_RELEASE_UPDATE: update to latest version.
60
+ DEFAULT_RAY_VERSION = "2.49.1" # RAY_RELEASE_UPDATE: update to latest version.
61
61
  DEFAULT_PYTHON_VERSION = "py311"
62
62
  RUNTIME_ENV_PACKAGE_FORMAT = "pkg_{content_hash}.zip"
63
63
 
@@ -520,7 +520,7 @@ class AnyscaleClientInterface(ABC):
520
520
  cloud_id: str,
521
521
  excludes: Optional[List[str]] = None,
522
522
  overwrite_existing_file: bool = False,
523
- cloud_deployment: Optional[str] = None,
523
+ cloud_resource_name: Optional[str] = None,
524
524
  ) -> str:
525
525
  """Upload the provided directory to cloud storage and return a URI for it.
526
526
 
@@ -535,17 +535,17 @@ class AnyscaleClientInterface(ABC):
535
535
  raise NotImplementedError
536
536
 
537
537
  @abstractmethod
538
- def upload_local_dir_to_cloud_storage_multi_deployment(
538
+ def upload_local_dir_to_cloud_storage_multi_cloud_resource(
539
539
  self,
540
540
  local_dir: str,
541
541
  *,
542
542
  cloud_id: str,
543
- cloud_deployments: List[Optional[str]],
543
+ cloud_resource_names: List[Optional[str]],
544
544
  excludes: Optional[List[str]] = None,
545
545
  overwrite_existing_file: bool = False,
546
546
  ) -> str:
547
547
  """Upload the provided directory to the object storage for each of the provided
548
- cloud deployments and return the bucket path of the uploaded file.
548
+ cloud resources and return the bucket path of the uploaded file.
549
549
 
550
550
  The directory will be zipped and the resulting bucket path will later be converted
551
551
  to a URI that can be used in a Ray runtime_env.
@@ -1019,12 +1019,12 @@ class FakeAnyscaleClient(AnyscaleClientInterface):
1019
1019
  cloud_id: str,
1020
1020
  excludes: Optional[List[str]] = None, # noqa: ARG002
1021
1021
  overwrite_existing_file: bool = False, # noqa: ARG002
1022
- cloud_deployment: Optional[str] = None,
1022
+ cloud_resource_name: Optional[str] = None,
1023
1023
  ) -> str:
1024
1024
  # Ensure that URIs are consistent for the same passed directory.
1025
1025
  bucket = self.CLOUD_BUCKET.format(cloud_id=cloud_id)
1026
- if cloud_deployment is not None:
1027
- bucket += f"_{cloud_deployment}"
1026
+ if cloud_resource_name is not None:
1027
+ bucket += f"_{cloud_resource_name}"
1028
1028
  if local_dir not in self._upload_uri_mapping:
1029
1029
  self._upload_uri_mapping[
1030
1030
  local_dir
@@ -1032,19 +1032,19 @@ class FakeAnyscaleClient(AnyscaleClientInterface):
1032
1032
 
1033
1033
  return self._upload_uri_mapping[local_dir]
1034
1034
 
1035
- def upload_local_dir_to_cloud_storage_multi_deployment(
1035
+ def upload_local_dir_to_cloud_storage_multi_cloud_resource(
1036
1036
  self,
1037
1037
  local_dir: str,
1038
1038
  *,
1039
1039
  cloud_id: str,
1040
- cloud_deployments: List[Optional[str]],
1040
+ cloud_resource_names: List[Optional[str]],
1041
1041
  excludes: Optional[List[str]] = None, # noqa: ARG002
1042
1042
  overwrite_existing_file: bool = False, # noqa: ARG002
1043
1043
  ) -> str:
1044
1044
  bucket = self.CLOUD_BUCKET.format(cloud_id=cloud_id)
1045
1045
  if local_dir not in self._upload_bucket_path_mapping:
1046
1046
  self._upload_bucket_path_mapping[local_dir] = (
1047
- cloud_deployments,
1047
+ cloud_resource_names,
1048
1048
  f"{bucket}/fake_pkg_{str(uuid.uuid4())}.zip",
1049
1049
  )
1050
1050
  return self._upload_bucket_path_mapping[local_dir][1]
@@ -13,9 +13,9 @@ from anyscale.aggregated_instance_usage.models import DownloadCSVFilters
13
13
  from anyscale.cloud.models import (
14
14
  AWSConfig,
15
15
  Cloud,
16
- CloudDeployment,
17
16
  CloudPermissionLevel,
18
17
  CloudProvider,
18
+ CloudResource,
19
19
  ComputeStack,
20
20
  CreateCloudCollaborator,
21
21
  FileStorage,
@@ -53,7 +53,7 @@ from anyscale.compute_config.models import (
53
53
  ComputeConfigVersion,
54
54
  HeadNodeConfig,
55
55
  MarketType,
56
- MultiDeploymentComputeConfig,
56
+ MultiResourceComputeConfig,
57
57
  WorkerNodeGroupConfig,
58
58
  )
59
59
  from anyscale.image.models import ImageBuild, ImageBuildStatus
@@ -330,7 +330,7 @@ ALL_MODULES = [
330
330
  ],
331
331
  models=[
332
332
  ComputeConfig,
333
- MultiDeploymentComputeConfig,
333
+ MultiResourceComputeConfig,
334
334
  HeadNodeConfig,
335
335
  WorkerNodeGroupConfig,
336
336
  MarketType,
@@ -448,8 +448,8 @@ ALL_MODULES = [
448
448
  cloud_commands.cloud_delete,
449
449
  cloud_commands.cloud_verify,
450
450
  cloud_commands.list_cloud,
451
- cloud_commands.cloud_deployment_create,
452
- cloud_commands.cloud_deployment_delete,
451
+ cloud_commands.cloud_resource_create,
452
+ cloud_commands.cloud_resource_delete,
453
453
  cloud_commands.cloud_config_get,
454
454
  cloud_commands.cloud_config_update,
455
455
  cloud_commands.cloud_set_default,
@@ -469,7 +469,7 @@ ALL_MODULES = [
469
469
  Cloud,
470
470
  CloudPermissionLevel,
471
471
  CreateCloudCollaborator,
472
- CloudDeployment,
472
+ CloudResource,
473
473
  ComputeStack,
474
474
  CloudProvider,
475
475
  NetworkingMode,
@@ -481,8 +481,8 @@ ALL_MODULES = [
481
481
  KubernetesConfig,
482
482
  ],
483
483
  cli_command_group_prefix={
484
- cloud_commands.cloud_deployment_create: "deployment",
485
- cloud_commands.cloud_deployment_delete: "deployment",
484
+ cloud_commands.cloud_resource_create: "resource",
485
+ cloud_commands.cloud_resource_delete: "resource",
486
486
  cloud_commands.cloud_config_get: "config",
487
487
  cloud_commands.cloud_config_update: "config",
488
488
  },
@@ -20,7 +20,11 @@ from anyscale._private.models.model_base import (
20
20
  ModelEnumType,
21
21
  ResultIterator,
22
22
  )
23
- from anyscale.commands.util import AnyscaleCommand, LegacyAnyscaleCommand
23
+ from anyscale.commands.util import (
24
+ AnyscaleCommand,
25
+ DeprecatedAnyscaleCommand,
26
+ LegacyAnyscaleCommand,
27
+ )
24
28
 
25
29
 
26
30
  ModelType = Union[ModelBaseType, ModelEnumType]
@@ -301,13 +305,20 @@ class MarkdownGenerator:
301
305
  raise ValueError(
302
306
  f"Config model '{t.__name__}' is missing a '__doc_yaml_example__'."
303
307
  )
304
- if isinstance(t, AnyscaleCommand) and not cli_example:
308
+ if (
309
+ isinstance(
310
+ t, (AnyscaleCommand, DeprecatedAnyscaleCommand, LegacyAnyscaleCommand)
311
+ )
312
+ and not cli_example
313
+ ):
305
314
  raise ValueError(
306
315
  f"CLI command '{t.name}' is missing a '__doc_cli_example__'."
307
316
  )
308
317
  if (
309
318
  not isinstance(t, ModelBaseType)
310
- and not isinstance(t, AnyscaleCommand)
319
+ and not isinstance(
320
+ t, (AnyscaleCommand, DeprecatedAnyscaleCommand, LegacyAnyscaleCommand)
321
+ )
311
322
  and not py_example
312
323
  ):
313
324
  raise ValueError(
@@ -321,8 +332,10 @@ class MarkdownGenerator:
321
332
  try:
322
333
  yaml.safe_load(yaml_example)
323
334
  except Exception as e: # noqa: BLE001
335
+ # For CLI commands, use t.name; for SDK functions/models, use t.__name__
336
+ name = getattr(t, "name", getattr(t, "__name__", str(t)))
324
337
  raise ValueError(
325
- f"'{t.__name__}.__doc_yaml_example__' is not valid YAML syntax"
338
+ f"'{name}.__doc_yaml_example__' is not valid YAML syntax"
326
339
  ) from e
327
340
 
328
341
  yaml_example = yaml_example.strip("\n")
@@ -334,8 +347,10 @@ class MarkdownGenerator:
334
347
  try:
335
348
  ast.parse(py_example)
336
349
  except Exception as e: # noqa: BLE001
350
+ # For CLI commands, use t.name; for SDK functions/models, use t.__name__
351
+ name = getattr(t, "name", getattr(t, "__name__", str(t)))
337
352
  raise ValueError(
338
- f"'{t.__name__}.__doc_py_example__' is not valid Python syntax"
353
+ f"'{name}.__doc_py_example__' is not valid Python syntax"
339
354
  ) from e
340
355
 
341
356
  py_example = py_example.strip("\n")
@@ -413,7 +428,7 @@ class MarkdownGenerator:
413
428
 
414
429
  return md
415
430
 
416
- def _gen_markdown_for_cli_command(
431
+ def _gen_markdown_for_cli_command( # noqa: PLR0912
417
432
  self, c: click.Command, *, cli_prefix: str
418
433
  ) -> str:
419
434
  """Generate a markdown section for a CLI command.
@@ -438,9 +453,31 @@ class MarkdownGenerator:
438
453
  else:
439
454
  new_c = c.get_new_cli()
440
455
  new_cli_prefix = c.get_new_prefix()
441
- md += ":::warning\n"
442
- md += f"This command is deprecated. Upgrade to [{new_cli_prefix} {new_c.name}]({self._get_cli_anchor(new_c, new_cli_prefix)}). \n"
443
- md += ":::\n"
456
+ if new_c and new_cli_prefix:
457
+ md += ":::warning\n"
458
+ md += f"This command is deprecated. Upgrade to [{new_cli_prefix} {new_c.name}]({self._get_cli_anchor(new_c, new_cli_prefix)}). \n"
459
+ md += ":::\n"
460
+ elif isinstance(c, DeprecatedAnyscaleCommand):
461
+ md = f'### `{cli_prefix} {c.name}` <span class="label-h3 label-deprecated">Deprecated</span>\n'
462
+ md += ":::warning[Deprecated]\n"
463
+ # Build deprecation message similar to the command itself
464
+ parts = []
465
+ if hasattr(c, "__deprecation_message__") and c.__deprecation_message__:
466
+ parts.append(c.__deprecation_message__)
467
+ else:
468
+ parts.append(f"Command '{c.name}' is deprecated")
469
+
470
+ if hasattr(c, "__removal_date__") and c.__removal_date__:
471
+ date_str = c._format_removal_date(c.__removal_date__) # noqa: SLF001
472
+ if date_str:
473
+ parts.append(f"and will be removed on {date_str}")
474
+
475
+ if hasattr(c, "__alternative__") and c.__alternative__:
476
+ parts.append(f"Please {c.__alternative__}")
477
+
478
+ deprecation_msg = ". ".join(parts) + "."
479
+ md += deprecation_msg + "\n"
480
+ md += ":::\n"
444
481
  elif isinstance(c, AnyscaleCommand) and c.is_alpha:
445
482
  md = f'### `{cli_prefix} {c.name}` <span class="label-h3 label-alpha">Alpha</span>\n'
446
483
  md += ":::warning\n"
@@ -478,7 +515,8 @@ class MarkdownGenerator:
478
515
  md += "\n"
479
516
 
480
517
  should_have_example = not (
481
- isinstance(c, LegacyAnyscaleCommand) or cli_prefix in CLI_NO_EXAMPLES
518
+ isinstance(c, (LegacyAnyscaleCommand, DeprecatedAnyscaleCommand))
519
+ or cli_prefix in CLI_NO_EXAMPLES
482
520
  )
483
521
  has_cli_example = hasattr(c, "__doc_cli_example__")
484
522
  if should_have_example or has_cli_example: