anyscale 0.26.69__py3-none-any.whl → 0.26.71__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 +126 -3
- anyscale/_private/anyscale_client/common.py +51 -2
- anyscale/_private/anyscale_client/fake_anyscale_client.py +103 -11
- anyscale/client/README.md +43 -4
- anyscale/client/openapi_client/__init__.py +30 -4
- anyscale/client/openapi_client/api/default_api.py +1769 -27
- anyscale/client/openapi_client/models/__init__.py +30 -4
- anyscale/client/openapi_client/models/api_key_info.py +29 -3
- anyscale/client/openapi_client/models/apply_autoscaling_config_update_model.py +350 -0
- anyscale/client/openapi_client/models/apply_multi_version_update_weights_update_model.py +152 -0
- anyscale/client/openapi_client/models/apply_production_service_multi_version_v2_model.py +207 -0
- anyscale/client/openapi_client/models/apply_production_service_v2_model.py +31 -3
- anyscale/client/openapi_client/models/apply_version_weight_update_model.py +181 -0
- anyscale/client/openapi_client/models/backend_server_api_product_models_catalog_client_models_table_metadata.py +546 -0
- anyscale/client/openapi_client/models/backend_server_api_product_models_data_catalogs_table_metadata.py +178 -0
- anyscale/client/openapi_client/models/baseimagesenum.py +139 -1
- anyscale/client/openapi_client/models/catalog_metadata.py +150 -0
- anyscale/client/openapi_client/models/cloud_data_bucket_file_type.py +2 -1
- anyscale/client/openapi_client/models/{oauthconnectionresponse_response.py → clouddeployment_response.py} +11 -11
- anyscale/client/openapi_client/models/column_info.py +265 -0
- anyscale/client/openapi_client/models/compute_node_type.py +29 -1
- anyscale/client/openapi_client/models/connection_metadata.py +206 -0
- anyscale/client/openapi_client/models/create_experimental_workspace.py +29 -1
- anyscale/client/openapi_client/models/create_workspace_from_template.py +29 -1
- anyscale/client/openapi_client/models/create_workspace_template_version.py +59 -3
- anyscale/client/openapi_client/models/data_catalog.py +45 -31
- anyscale/client/openapi_client/models/data_catalog_connection.py +74 -58
- anyscale/client/openapi_client/models/{ha_job_event_level.py → data_catalog_object_type.py} +7 -8
- anyscale/client/openapi_client/models/data_catalog_schema.py +324 -0
- anyscale/client/openapi_client/models/data_catalog_table.py +437 -0
- anyscale/client/openapi_client/models/data_catalog_volume.py +437 -0
- anyscale/client/openapi_client/models/datacatalogschema_list_response.py +147 -0
- anyscale/client/openapi_client/models/datacatalogtable_list_response.py +147 -0
- anyscale/client/openapi_client/models/datacatalogvolume_list_response.py +147 -0
- anyscale/client/openapi_client/models/decorated_list_service_api_model.py +58 -1
- anyscale/client/openapi_client/models/decorated_production_service_v2_api_model.py +60 -3
- anyscale/client/openapi_client/models/decorated_serve_deployment.py +27 -1
- anyscale/client/openapi_client/models/decorated_service_event_api_model.py +3 -3
- anyscale/client/openapi_client/models/decoratedproductionservicev2_versionapimodel_response.py +121 -0
- anyscale/client/openapi_client/models/describe_machine_pool_machines_filters.py +33 -5
- anyscale/client/openapi_client/models/describe_machine_pool_requests_filters.py +33 -5
- anyscale/client/openapi_client/models/describe_machine_pool_workloads_filters.py +33 -5
- anyscale/client/openapi_client/models/{service_event_level.py → entity_type.py} +9 -9
- anyscale/client/openapi_client/models/event_level.py +2 -1
- anyscale/client/openapi_client/models/job_event_fields.py +206 -0
- anyscale/client/openapi_client/models/machine_type_partition_filter.py +152 -0
- anyscale/client/openapi_client/models/partition_info.py +30 -1
- anyscale/client/openapi_client/models/physical_resources.py +178 -0
- anyscale/client/openapi_client/models/production_job_event.py +3 -3
- anyscale/client/openapi_client/models/rollout_strategy.py +2 -1
- anyscale/client/openapi_client/models/schema_metadata.py +150 -0
- anyscale/client/openapi_client/models/service_event_fields.py +318 -0
- anyscale/client/openapi_client/models/sso_config.py +18 -18
- anyscale/client/openapi_client/models/supportedbaseimagesenum.py +139 -1
- anyscale/client/openapi_client/models/table_data_preview.py +209 -0
- anyscale/client/openapi_client/models/task_summary_config.py +29 -3
- anyscale/client/openapi_client/models/task_table_config.py +29 -3
- anyscale/client/openapi_client/models/unified_event.py +377 -0
- anyscale/client/openapi_client/models/unified_origin_filter.py +113 -0
- anyscale/client/openapi_client/models/unifiedevent_list_response.py +147 -0
- anyscale/client/openapi_client/models/volume_metadata.py +150 -0
- anyscale/client/openapi_client/models/worker_node_type.py +29 -1
- anyscale/client/openapi_client/models/workspace_event_fields.py +122 -0
- anyscale/client/openapi_client/models/workspace_template_version.py +58 -1
- anyscale/client/openapi_client/models/workspace_template_version_data_object.py +58 -1
- anyscale/cloud/models.py +2 -2
- anyscale/commands/cloud_commands.py +133 -2
- anyscale/commands/job_commands.py +121 -1
- anyscale/commands/job_queue_commands.py +99 -2
- anyscale/commands/service_commands.py +267 -67
- anyscale/commands/setup_k8s.py +546 -31
- anyscale/commands/util.py +104 -1
- anyscale/commands/workspace_commands.py +123 -5
- anyscale/commands/workspace_commands_v2.py +17 -1
- anyscale/compute_config/_private/compute_config_sdk.py +25 -12
- anyscale/compute_config/models.py +15 -0
- anyscale/controllers/cloud_controller.py +15 -2
- anyscale/controllers/job_controller.py +12 -0
- anyscale/controllers/kubernetes_verifier.py +80 -66
- anyscale/controllers/workspace_controller.py +67 -5
- anyscale/job/_private/job_sdk.py +50 -2
- anyscale/job/commands.py +3 -0
- anyscale/job/models.py +16 -0
- anyscale/job_queue/__init__.py +37 -1
- anyscale/job_queue/_private/job_queue_sdk.py +28 -1
- anyscale/job_queue/commands.py +61 -1
- anyscale/sdk/anyscale_client/__init__.py +1 -0
- anyscale/sdk/anyscale_client/api/default_api.py +12 -2
- anyscale/sdk/anyscale_client/models/__init__.py +1 -0
- anyscale/sdk/anyscale_client/models/apply_production_service_v2_model.py +31 -3
- anyscale/sdk/anyscale_client/models/apply_service_model.py +31 -3
- anyscale/sdk/anyscale_client/models/baseimagesenum.py +139 -1
- anyscale/sdk/anyscale_client/models/compute_node_type.py +29 -1
- anyscale/sdk/anyscale_client/models/physical_resources.py +178 -0
- anyscale/sdk/anyscale_client/models/rollout_strategy.py +2 -1
- anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +139 -1
- anyscale/sdk/anyscale_client/models/worker_node_type.py +29 -1
- anyscale/service/__init__.py +51 -3
- anyscale/service/_private/service_sdk.py +481 -58
- anyscale/service/commands.py +90 -4
- anyscale/service/models.py +56 -0
- anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
- anyscale/version.py +1 -1
- anyscale/workspace/_private/workspace_sdk.py +1 -0
- anyscale/workspace/models.py +19 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.71.dist-info}/METADATA +1 -1
- {anyscale-0.26.69.dist-info → anyscale-0.26.71.dist-info}/RECORD +112 -85
- anyscale/client/openapi_client/models/o_auth_connection_response.py +0 -229
- {anyscale-0.26.69.dist-info → anyscale-0.26.71.dist-info}/WHEEL +0 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.71.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.71.dist-info}/licenses/LICENSE +0 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.71.dist-info}/licenses/NOTICE +0 -0
- {anyscale-0.26.69.dist-info → anyscale-0.26.71.dist-info}/top_level.txt +0 -0
anyscale/service/commands.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import List, Optional, Union
|
|
1
|
+
from typing import Dict, List, Optional, Union
|
|
2
2
|
|
|
3
3
|
from anyscale._private.models.model_base import ResultIterator
|
|
4
4
|
from anyscale._private.sdk import sdk_command
|
|
@@ -32,10 +32,14 @@ anyscale.service.deploy(
|
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
_DEPLOY_ARG_DOCSTRINGS = {
|
|
35
|
-
"
|
|
35
|
+
"configs": "The config options defining the service.",
|
|
36
36
|
"in_place": "Perform an in-place upgrade without starting a new cluster. This can be used for faster iteration during development but is *not* currently recommended for production deploys. This *cannot* be used to change cluster-level options such as image and compute config (they will be ignored).",
|
|
37
37
|
"canary_percent": "The percentage of traffic to send to the canary version of the service (0-100). This can be used to manually shift traffic toward (or away from) the canary version. If not provided, traffic will be shifted incrementally toward the canary version until it reaches 100. Not supported when using --in-place. This is ignored when restarting a service or creating a new service.",
|
|
38
38
|
"max_surge_percent": "Amount of excess capacity allowed to be used while updating the service (0-100). Defaults to 100. Not supported when using --in-place.",
|
|
39
|
+
"versions": "Enable multi-version deployment by providing a JSON array of objects or a JSON object in text format. Defines the version name, traffic and capacity percents per version. Capacity defaults to traffic.",
|
|
40
|
+
"name": "Name of the service. When running in a workspace, this defaults to the workspace name.",
|
|
41
|
+
"cloud": "The Anyscale Cloud of this workload. If not provided, the organization default will be used (or, if running in a workspace, the cloud of the workspace).",
|
|
42
|
+
"project": "Named project to use for the service. If not provided, the default project for the cloud will be used (or, if running in a workspace, the project of the workspace).",
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
|
|
@@ -46,11 +50,15 @@ _DEPLOY_ARG_DOCSTRINGS = {
|
|
|
46
50
|
arg_docstrings=_DEPLOY_ARG_DOCSTRINGS,
|
|
47
51
|
)
|
|
48
52
|
def deploy(
|
|
49
|
-
|
|
53
|
+
configs: Union[ServiceConfig, List[ServiceConfig]],
|
|
50
54
|
*,
|
|
51
55
|
in_place: bool = False,
|
|
52
56
|
canary_percent: Optional[int] = None,
|
|
53
57
|
max_surge_percent: Optional[int] = None,
|
|
58
|
+
versions: Optional[str] = None,
|
|
59
|
+
name: Optional[str] = None,
|
|
60
|
+
cloud: Optional[str] = None,
|
|
61
|
+
project: Optional[str] = None,
|
|
54
62
|
_private_sdk: Optional[PrivateServiceSDK] = None,
|
|
55
63
|
) -> str:
|
|
56
64
|
"""Deploy a service.
|
|
@@ -62,10 +70,14 @@ def deploy(
|
|
|
62
70
|
Returns the id of the deployed service.
|
|
63
71
|
"""
|
|
64
72
|
return _private_sdk.deploy( # type: ignore
|
|
65
|
-
|
|
73
|
+
configs=configs,
|
|
66
74
|
in_place=in_place,
|
|
67
75
|
canary_percent=canary_percent,
|
|
68
76
|
max_surge_percent=max_surge_percent,
|
|
77
|
+
versions=versions,
|
|
78
|
+
name=name,
|
|
79
|
+
cloud=cloud,
|
|
80
|
+
project=project,
|
|
69
81
|
)
|
|
70
82
|
|
|
71
83
|
|
|
@@ -311,6 +323,77 @@ _CONTROLLER_LOGS_ARG_DOCSTRINGS = {
|
|
|
311
323
|
"max_lines": "The number of log lines to be fetched. If not provided, 1000 lines will be fetched.",
|
|
312
324
|
}
|
|
313
325
|
|
|
326
|
+
# SDK docs for Service tag operations
|
|
327
|
+
_TAGS_ADD_EXAMPLE = """
|
|
328
|
+
import anyscale
|
|
329
|
+
|
|
330
|
+
anyscale.service.add_tags(id="svc_123", tags={"team": "mlops", "env": "prod"})
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
_TAGS_ADD_ARG_DOCSTRINGS = {
|
|
334
|
+
"id": "ID of the service. Provide either id or name.",
|
|
335
|
+
"name": "Name of the service. Provide either id or name.",
|
|
336
|
+
"cloud": "Cloud name (used when resolving by name).",
|
|
337
|
+
"project": "Project name (used when resolving by name).",
|
|
338
|
+
"tags": "Key/value tags to upsert as a map {key: value}.",
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
_TAGS_REMOVE_EXAMPLE = """
|
|
342
|
+
import anyscale
|
|
343
|
+
|
|
344
|
+
anyscale.service.remove_tags(id="svc_123", keys=["team", "env"])
|
|
345
|
+
"""
|
|
346
|
+
|
|
347
|
+
_TAGS_REMOVE_ARG_DOCSTRINGS = {
|
|
348
|
+
"id": "ID of the service. Provide either id or name.",
|
|
349
|
+
"name": "Name of the service. Provide either id or name.",
|
|
350
|
+
"cloud": "Cloud name (used when resolving by name).",
|
|
351
|
+
"project": "Project name (used when resolving by name).",
|
|
352
|
+
"keys": "List of tag keys to remove.",
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
@sdk_command(
|
|
357
|
+
_SERVICE_SDK_SINGLETON_KEY,
|
|
358
|
+
PrivateServiceSDK,
|
|
359
|
+
doc_py_example=_TAGS_ADD_EXAMPLE,
|
|
360
|
+
arg_docstrings=_TAGS_ADD_ARG_DOCSTRINGS,
|
|
361
|
+
)
|
|
362
|
+
def add_tags(
|
|
363
|
+
*,
|
|
364
|
+
id: Optional[str] = None, # noqa: A002
|
|
365
|
+
name: Optional[str] = None,
|
|
366
|
+
cloud: Optional[str] = None,
|
|
367
|
+
project: Optional[str] = None,
|
|
368
|
+
tags: Dict[str, str],
|
|
369
|
+
_private_sdk: Optional[PrivateServiceSDK] = None,
|
|
370
|
+
) -> None:
|
|
371
|
+
"""Upsert (add/update) tag key/value pairs for a service."""
|
|
372
|
+
return _private_sdk.add_tags( # type: ignore
|
|
373
|
+
id=id, name=name, cloud=cloud, project=project, tags=tags
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
@sdk_command(
|
|
378
|
+
_SERVICE_SDK_SINGLETON_KEY,
|
|
379
|
+
PrivateServiceSDK,
|
|
380
|
+
doc_py_example=_TAGS_REMOVE_EXAMPLE,
|
|
381
|
+
arg_docstrings=_TAGS_REMOVE_ARG_DOCSTRINGS,
|
|
382
|
+
)
|
|
383
|
+
def remove_tags(
|
|
384
|
+
*,
|
|
385
|
+
id: Optional[str] = None, # noqa: A002
|
|
386
|
+
name: Optional[str] = None,
|
|
387
|
+
cloud: Optional[str] = None,
|
|
388
|
+
project: Optional[str] = None,
|
|
389
|
+
keys: List[str],
|
|
390
|
+
_private_sdk: Optional[PrivateServiceSDK] = None,
|
|
391
|
+
) -> None:
|
|
392
|
+
"""Remove tags by key from a service."""
|
|
393
|
+
return _private_sdk.remove_tags( # type: ignore
|
|
394
|
+
id=id, name=name, cloud=cloud, project=project, keys=keys
|
|
395
|
+
)
|
|
396
|
+
|
|
314
397
|
|
|
315
398
|
# This is a private command that is not exposed to the user.
|
|
316
399
|
@sdk_command(
|
|
@@ -363,6 +446,7 @@ _LIST_ARG_DOCSTRINGS = {
|
|
|
363
446
|
"cloud": "Name of the Anyscale Cloud to search in.",
|
|
364
447
|
"project": "Name of the Anyscale Project to search in.",
|
|
365
448
|
"include_archived": "Include archived services (default: False).",
|
|
449
|
+
"tags_filter": "Filter services by tags as a dict: {key: [values...]}. Values with the same key are ORed; keys are ANDed.",
|
|
366
450
|
# Paging
|
|
367
451
|
"max_items": "Maximum **total** number of items to yield (default: iterate all).",
|
|
368
452
|
"page_size": "Number of items to fetch per API request (default: API default).",
|
|
@@ -390,6 +474,7 @@ def list( # noqa: A001
|
|
|
390
474
|
cloud: Optional[str] = None,
|
|
391
475
|
project: Optional[str] = None,
|
|
392
476
|
include_archived: bool = False,
|
|
477
|
+
tags_filter: Optional[Dict[str, List[str]]] = None,
|
|
393
478
|
# Paging
|
|
394
479
|
max_items: Optional[int] = None,
|
|
395
480
|
page_size: Optional[int] = None,
|
|
@@ -408,6 +493,7 @@ def list( # noqa: A001
|
|
|
408
493
|
cloud=cloud,
|
|
409
494
|
project=project,
|
|
410
495
|
include_archived=include_archived,
|
|
496
|
+
tags_filter=tags_filter,
|
|
411
497
|
max_items=max_items,
|
|
412
498
|
page_size=page_size,
|
|
413
499
|
sort_field=sort_field,
|
anyscale/service/models.py
CHANGED
|
@@ -213,6 +213,9 @@ tracing_config: # (Optional) Configuration options for tracing.
|
|
|
213
213
|
enabled: true
|
|
214
214
|
exporter_import_path: my_module:custom_tracing_exporter
|
|
215
215
|
sampling_ratio: 1.0
|
|
216
|
+
tags:
|
|
217
|
+
team: serving
|
|
218
|
+
cost-center: eng
|
|
216
219
|
"""
|
|
217
220
|
|
|
218
221
|
# Override the `name` field from `WorkloadConfig` so we can document it separately for jobs and services.
|
|
@@ -231,6 +234,16 @@ tracing_config: # (Optional) Configuration options for tracing.
|
|
|
231
234
|
},
|
|
232
235
|
)
|
|
233
236
|
|
|
237
|
+
version_name: Optional[str] = field(
|
|
238
|
+
default=None, metadata={"docstring": "Unique name of the version."},
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def _validate_version_name(self, version_name: Optional[str]):
|
|
242
|
+
# Allow None if optional; enforce non-empty string if required
|
|
243
|
+
if version_name is None:
|
|
244
|
+
return None
|
|
245
|
+
return version_name
|
|
246
|
+
|
|
234
247
|
def _validate_applications(self, applications: List[Dict[str, Any]]):
|
|
235
248
|
if not isinstance(applications, list):
|
|
236
249
|
raise TypeError("'applications' must be a list.")
|
|
@@ -390,6 +403,19 @@ tracing_config: # (Optional) Configuration options for tracing.
|
|
|
390
403
|
|
|
391
404
|
return tracing_config
|
|
392
405
|
|
|
406
|
+
tags: Optional[Dict[str, str]] = field(
|
|
407
|
+
default=None, metadata={"docstring": "Tags to associate with the service."},
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
def _validate_tags(self, tags: Optional[Dict[str, str]]):
|
|
411
|
+
if tags is None:
|
|
412
|
+
return
|
|
413
|
+
if not isinstance(tags, dict):
|
|
414
|
+
raise TypeError("'tags' must be a Dict[str, str].")
|
|
415
|
+
for k, v in tags.items():
|
|
416
|
+
if not isinstance(k, str) or not isinstance(v, str):
|
|
417
|
+
raise TypeError("'tags' must be a Dict[str, str].")
|
|
418
|
+
|
|
393
419
|
|
|
394
420
|
class ServiceState(ModelEnum):
|
|
395
421
|
"""Current state of a service."""
|
|
@@ -487,6 +513,7 @@ id: service2_uz6l8yhy2as5wrer3shzj6kh67
|
|
|
487
513
|
state: RUNNING
|
|
488
514
|
primary_version:
|
|
489
515
|
id: 601bd56c4b
|
|
516
|
+
name: v1
|
|
490
517
|
state: RUNNING
|
|
491
518
|
weight: 100
|
|
492
519
|
created_at: 2025-04-18 17:21:28.323174+00:00
|
|
@@ -502,6 +529,15 @@ primary_version:
|
|
|
502
529
|
if not isinstance(id, str):
|
|
503
530
|
raise TypeError("'id' must be a string.")
|
|
504
531
|
|
|
532
|
+
name: str = field(
|
|
533
|
+
metadata={"docstring": "Human-readable name of the service version."}
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
def _validate_name(self, name: str):
|
|
537
|
+
if name is None:
|
|
538
|
+
return None
|
|
539
|
+
return name
|
|
540
|
+
|
|
505
541
|
state: Union[ServiceVersionState, str] = field(
|
|
506
542
|
metadata={"docstring": "Current state of the service version."}
|
|
507
543
|
)
|
|
@@ -688,6 +724,26 @@ primary_version:
|
|
|
688
724
|
if project is not None and not isinstance(project, str):
|
|
689
725
|
raise TypeError("project must be a string.")
|
|
690
726
|
|
|
727
|
+
versions: Optional[List[ServiceVersionStatus]] = field(
|
|
728
|
+
default=None,
|
|
729
|
+
repr=False,
|
|
730
|
+
metadata={
|
|
731
|
+
"docstring": "All active versions of the service. For multi-version services, this contains all versions with their traffic weights."
|
|
732
|
+
},
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
def _validate_versions(
|
|
736
|
+
self, versions: Optional[List[ServiceVersionStatus]]
|
|
737
|
+
) -> Optional[List[ServiceVersionStatus]]:
|
|
738
|
+
if versions is None:
|
|
739
|
+
return None
|
|
740
|
+
if not isinstance(versions, list):
|
|
741
|
+
raise TypeError("'versions' must be a list.")
|
|
742
|
+
for v in versions:
|
|
743
|
+
if not isinstance(v, ServiceVersionStatus):
|
|
744
|
+
raise TypeError("'versions' must be a list of ServiceVersionStatus.")
|
|
745
|
+
return versions
|
|
746
|
+
|
|
691
747
|
|
|
692
748
|
class ServiceSortField(ModelEnum):
|
|
693
749
|
"""Fields available for sorting services."""
|
anyscale/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.26.
|
|
1
|
+
__version__ = "0.26.71"
|
anyscale/workspace/models.py
CHANGED
|
@@ -53,6 +53,9 @@ idle_termination_minutes: 220
|
|
|
53
53
|
env_vars:
|
|
54
54
|
key: value
|
|
55
55
|
requirements: /tmp/requirements.txt
|
|
56
|
+
tags:
|
|
57
|
+
team: mlops
|
|
58
|
+
env: prod
|
|
56
59
|
"""
|
|
57
60
|
|
|
58
61
|
name: Optional[str] = field(
|
|
@@ -88,6 +91,19 @@ requirements: /tmp/requirements.txt
|
|
|
88
91
|
if containerfile is not None and not isinstance(containerfile, str):
|
|
89
92
|
raise TypeError("'containerfile' must be a string.")
|
|
90
93
|
|
|
94
|
+
tags: Optional[Dict[str, str]] = field(
|
|
95
|
+
default=None, metadata={"docstring": "Tags to associate with the workspace."},
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def _validate_tags(self, tags: Optional[Dict[str, str]]):
|
|
99
|
+
if tags is None:
|
|
100
|
+
return
|
|
101
|
+
if not isinstance(tags, dict):
|
|
102
|
+
raise TypeError("'tags' must be a Dict[str, str].")
|
|
103
|
+
for k, v in tags.items():
|
|
104
|
+
if not isinstance(k, str) or not isinstance(v, str):
|
|
105
|
+
raise TypeError("'tags' must be a Dict[str, str].")
|
|
106
|
+
|
|
91
107
|
compute_config: Union[ComputeConfigType, Dict, str, None] = field(
|
|
92
108
|
default=None,
|
|
93
109
|
metadata={
|
|
@@ -215,6 +231,9 @@ idle_termination_minutes: 220
|
|
|
215
231
|
env_vars:
|
|
216
232
|
key: value
|
|
217
233
|
requirements: /tmp/requirements.txt
|
|
234
|
+
tags:
|
|
235
|
+
team: mlops
|
|
236
|
+
env: prod
|
|
218
237
|
"""
|
|
219
238
|
|
|
220
239
|
project: Optional[str] = field(
|