zenml-nightly 0.75.0.dev20250313__py3-none-any.whl → 0.75.0.dev20250315__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.
- zenml/VERSION +1 -1
- zenml/analytics/context.py +4 -4
- zenml/analytics/enums.py +2 -2
- zenml/artifacts/utils.py +2 -2
- zenml/cli/__init__.py +8 -9
- zenml/cli/base.py +2 -2
- zenml/cli/code_repository.py +1 -1
- zenml/cli/login.py +21 -18
- zenml/cli/pipeline.py +3 -3
- zenml/cli/project.py +172 -0
- zenml/cli/server.py +5 -5
- zenml/cli/service_accounts.py +0 -1
- zenml/cli/service_connectors.py +15 -16
- zenml/cli/stack.py +0 -2
- zenml/cli/stack_components.py +2 -2
- zenml/cli/utils.py +3 -3
- zenml/client.py +352 -341
- zenml/config/global_config.py +41 -43
- zenml/config/server_config.py +9 -9
- zenml/constants.py +5 -3
- zenml/event_hub/event_hub.py +1 -1
- zenml/integrations/gcp/__init__.py +1 -0
- zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py +5 -0
- zenml/integrations/gcp/flavors/vertex_step_operator_flavor.py +5 -28
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +125 -78
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +7 -6
- zenml/integrations/gcp/vertex_custom_job_parameters.py +50 -0
- zenml/integrations/mlflow/steps/mlflow_registry.py +3 -3
- zenml/integrations/wandb/__init__.py +1 -1
- zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py +29 -9
- zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +2 -0
- zenml/login/credentials.py +26 -27
- zenml/login/credentials_store.py +5 -5
- zenml/login/pro/client.py +9 -9
- zenml/login/pro/utils.py +8 -8
- zenml/login/pro/{tenant → workspace}/__init__.py +1 -1
- zenml/login/pro/{tenant → workspace}/client.py +25 -25
- zenml/login/pro/{tenant → workspace}/models.py +27 -28
- zenml/model/model.py +2 -2
- zenml/model_registries/base_model_registry.py +1 -1
- zenml/models/__init__.py +29 -29
- zenml/models/v2/base/filter.py +1 -1
- zenml/models/v2/base/scoped.py +49 -53
- zenml/models/v2/core/action.py +12 -12
- zenml/models/v2/core/artifact.py +15 -15
- zenml/models/v2/core/artifact_version.py +15 -15
- zenml/models/v2/core/code_repository.py +12 -12
- zenml/models/v2/core/event_source.py +12 -12
- zenml/models/v2/core/model.py +26 -18
- zenml/models/v2/core/model_version.py +15 -15
- zenml/models/v2/core/pipeline.py +15 -15
- zenml/models/v2/core/pipeline_build.py +14 -14
- zenml/models/v2/core/pipeline_deployment.py +12 -14
- zenml/models/v2/core/pipeline_run.py +16 -16
- zenml/models/v2/core/project.py +203 -0
- zenml/models/v2/core/run_metadata.py +2 -2
- zenml/models/v2/core/run_template.py +15 -15
- zenml/models/v2/core/schedule.py +12 -12
- zenml/models/v2/core/secret.py +1 -1
- zenml/models/v2/core/service.py +14 -14
- zenml/models/v2/core/step_run.py +13 -13
- zenml/models/v2/core/tag.py +96 -3
- zenml/models/v2/core/trigger.py +13 -13
- zenml/models/v2/core/trigger_execution.py +2 -2
- zenml/models/v2/core/user.py +0 -17
- zenml/models/v2/misc/server_models.py +6 -6
- zenml/models/v2/misc/statistics.py +4 -4
- zenml/orchestrators/cache_utils.py +7 -7
- zenml/orchestrators/input_utils.py +1 -1
- zenml/orchestrators/step_launcher.py +1 -1
- zenml/orchestrators/step_run_utils.py +3 -3
- zenml/orchestrators/utils.py +4 -4
- zenml/pipelines/build_utils.py +2 -2
- zenml/pipelines/pipeline_definition.py +5 -5
- zenml/pipelines/run_utils.py +1 -1
- zenml/service_connectors/service_connector.py +0 -3
- zenml/service_connectors/service_connector_utils.py +0 -1
- zenml/stack/stack.py +0 -1
- zenml/steps/base_step.py +10 -2
- zenml/utils/dashboard_utils.py +1 -1
- zenml/utils/tag_utils.py +0 -12
- zenml/zen_server/cloud_utils.py +3 -3
- zenml/zen_server/feature_gate/endpoint_utils.py +1 -1
- zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +1 -1
- zenml/zen_server/rbac/endpoint_utils.py +17 -17
- zenml/zen_server/rbac/models.py +47 -22
- zenml/zen_server/rbac/rbac_sql_zen_store.py +3 -3
- zenml/zen_server/rbac/utils.py +23 -25
- zenml/zen_server/rbac/zenml_cloud_rbac.py +7 -74
- zenml/zen_server/routers/artifact_version_endpoints.py +10 -10
- zenml/zen_server/routers/auth_endpoints.py +6 -6
- zenml/zen_server/routers/code_repositories_endpoints.py +12 -14
- zenml/zen_server/routers/model_versions_endpoints.py +13 -15
- zenml/zen_server/routers/models_endpoints.py +7 -9
- zenml/zen_server/routers/pipeline_builds_endpoints.py +14 -16
- zenml/zen_server/routers/pipeline_deployments_endpoints.py +13 -15
- zenml/zen_server/routers/pipelines_endpoints.py +16 -18
- zenml/zen_server/routers/{workspaces_endpoints.py → projects_endpoints.py} +111 -68
- zenml/zen_server/routers/run_metadata_endpoints.py +7 -9
- zenml/zen_server/routers/run_templates_endpoints.py +15 -17
- zenml/zen_server/routers/runs_endpoints.py +12 -14
- zenml/zen_server/routers/schedule_endpoints.py +12 -14
- zenml/zen_server/routers/secrets_endpoints.py +1 -3
- zenml/zen_server/routers/server_endpoints.py +7 -7
- zenml/zen_server/routers/service_connectors_endpoints.py +11 -13
- zenml/zen_server/routers/service_endpoints.py +7 -9
- zenml/zen_server/routers/stack_components_endpoints.py +9 -11
- zenml/zen_server/routers/stacks_endpoints.py +9 -11
- zenml/zen_server/routers/steps_endpoints.py +6 -6
- zenml/zen_server/routers/users_endpoints.py +5 -43
- zenml/zen_server/template_execution/utils.py +4 -4
- zenml/zen_server/utils.py +10 -10
- zenml/zen_server/zen_server_api.py +6 -5
- zenml/zen_stores/base_zen_store.py +38 -42
- zenml/zen_stores/migrations/versions/12eff0206201_rename_workspace_to_project.py +768 -0
- zenml/zen_stores/migrations/versions/41b28cae31ce_make_artifacts_workspace_scoped.py +3 -3
- zenml/zen_stores/migrations/versions/cbc6acd71f92_add_workspace_display_name.py +58 -0
- zenml/zen_stores/rest_zen_store.py +55 -63
- zenml/zen_stores/schemas/__init__.py +2 -2
- zenml/zen_stores/schemas/action_schemas.py +9 -9
- zenml/zen_stores/schemas/artifact_schemas.py +15 -17
- zenml/zen_stores/schemas/code_repository_schemas.py +16 -18
- zenml/zen_stores/schemas/event_source_schemas.py +9 -9
- zenml/zen_stores/schemas/model_schemas.py +15 -17
- zenml/zen_stores/schemas/pipeline_build_schemas.py +7 -7
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +7 -7
- zenml/zen_stores/schemas/pipeline_run_schemas.py +9 -9
- zenml/zen_stores/schemas/pipeline_schemas.py +9 -9
- zenml/zen_stores/schemas/{workspace_schemas.py → project_schemas.py} +47 -41
- zenml/zen_stores/schemas/run_metadata_schemas.py +5 -5
- zenml/zen_stores/schemas/run_template_schemas.py +9 -9
- zenml/zen_stores/schemas/schedule_schema.py +9 -9
- zenml/zen_stores/schemas/service_schemas.py +7 -7
- zenml/zen_stores/schemas/step_run_schemas.py +7 -7
- zenml/zen_stores/schemas/trigger_schemas.py +9 -9
- zenml/zen_stores/schemas/user_schemas.py +0 -12
- zenml/zen_stores/sql_zen_store.py +318 -275
- zenml/zen_stores/zen_store_interface.py +56 -70
- {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/METADATA +1 -1
- {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/RECORD +143 -140
- zenml/cli/workspace.py +0 -160
- zenml/models/v2/core/workspace.py +0 -131
- {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/entry_points.txt +0 -0
zenml/models/v2/core/tag.py
CHANGED
@@ -14,12 +14,12 @@
|
|
14
14
|
"""Models representing tags."""
|
15
15
|
|
16
16
|
import random
|
17
|
-
from typing import Optional
|
17
|
+
from typing import TYPE_CHECKING, ClassVar, List, Optional, Type, TypeVar
|
18
18
|
|
19
|
-
from pydantic import Field
|
19
|
+
from pydantic import Field, field_validator
|
20
20
|
|
21
21
|
from zenml.constants import STR_FIELD_MAX_LENGTH
|
22
|
-
from zenml.enums import ColorVariants
|
22
|
+
from zenml.enums import ColorVariants, TaggableResourceTypes
|
23
23
|
from zenml.models.v2.base.base import BaseUpdate
|
24
24
|
from zenml.models.v2.base.scoped import (
|
25
25
|
UserScopedFilter,
|
@@ -29,6 +29,14 @@ from zenml.models.v2.base.scoped import (
|
|
29
29
|
UserScopedResponseMetadata,
|
30
30
|
UserScopedResponseResources,
|
31
31
|
)
|
32
|
+
from zenml.utils.uuid_utils import is_valid_uuid
|
33
|
+
|
34
|
+
if TYPE_CHECKING:
|
35
|
+
from sqlalchemy.sql.elements import ColumnElement
|
36
|
+
|
37
|
+
from zenml.zen_stores.schemas import BaseSchema
|
38
|
+
|
39
|
+
AnySchema = TypeVar("AnySchema", bound="BaseSchema")
|
32
40
|
|
33
41
|
# ------------------ Request Model ------------------
|
34
42
|
|
@@ -49,6 +57,28 @@ class TagRequest(UserScopedRequest):
|
|
49
57
|
default_factory=lambda: random.choice(list(ColorVariants)),
|
50
58
|
)
|
51
59
|
|
60
|
+
@field_validator("name")
|
61
|
+
@classmethod
|
62
|
+
def validate_name_not_uuid(cls, value: str) -> str:
|
63
|
+
"""Validates that the tag name is not a UUID.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
value: The tag name to validate.
|
67
|
+
|
68
|
+
Returns:
|
69
|
+
The validated tag name.
|
70
|
+
|
71
|
+
Raises:
|
72
|
+
ValueError: If the tag name can be converted
|
73
|
+
to a UUID.
|
74
|
+
"""
|
75
|
+
if is_valid_uuid(value):
|
76
|
+
raise ValueError(
|
77
|
+
"Tag names cannot be UUIDs or strings that "
|
78
|
+
"can be converted to UUIDs."
|
79
|
+
)
|
80
|
+
return value
|
81
|
+
|
52
82
|
|
53
83
|
# ------------------ Update Model ------------------
|
54
84
|
|
@@ -60,6 +90,27 @@ class TagUpdate(BaseUpdate):
|
|
60
90
|
exclusive: Optional[bool] = None
|
61
91
|
color: Optional[ColorVariants] = None
|
62
92
|
|
93
|
+
@field_validator("name")
|
94
|
+
@classmethod
|
95
|
+
def validate_name_not_uuid(cls, value: Optional[str]) -> Optional[str]:
|
96
|
+
"""Validates that the tag name is not a UUID.
|
97
|
+
|
98
|
+
Args:
|
99
|
+
value: The tag name to validate.
|
100
|
+
|
101
|
+
Returns:
|
102
|
+
The validated tag name.
|
103
|
+
|
104
|
+
Raises:
|
105
|
+
ValueError: If the tag name can be converted to a UUID.
|
106
|
+
"""
|
107
|
+
if value is not None and is_valid_uuid(value):
|
108
|
+
raise ValueError(
|
109
|
+
"Tag names cannot be UUIDs or strings that "
|
110
|
+
"can be converted to UUIDs."
|
111
|
+
)
|
112
|
+
return value
|
113
|
+
|
63
114
|
|
64
115
|
# ------------------ Response Model ------------------
|
65
116
|
|
@@ -143,6 +194,11 @@ class TagResponse(
|
|
143
194
|
class TagFilter(UserScopedFilter):
|
144
195
|
"""Model to enable advanced filtering of all tags."""
|
145
196
|
|
197
|
+
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
|
198
|
+
*UserScopedFilter.FILTER_EXCLUDE_FIELDS,
|
199
|
+
"resource_type",
|
200
|
+
]
|
201
|
+
|
146
202
|
name: Optional[str] = Field(
|
147
203
|
description="The unique title of the tag.", default=None
|
148
204
|
)
|
@@ -153,3 +209,40 @@ class TagFilter(UserScopedFilter):
|
|
153
209
|
description="The flag signifying whether the tag is an exclusive tag.",
|
154
210
|
default=None,
|
155
211
|
)
|
212
|
+
resource_type: Optional[TaggableResourceTypes] = Field(
|
213
|
+
description="Filter tags associated with a specific resource type.",
|
214
|
+
default=None,
|
215
|
+
)
|
216
|
+
|
217
|
+
def get_custom_filters(
|
218
|
+
self, table: Type["AnySchema"]
|
219
|
+
) -> List["ColumnElement[bool]"]:
|
220
|
+
"""Get custom filters.
|
221
|
+
|
222
|
+
Args:
|
223
|
+
table: The query table.
|
224
|
+
|
225
|
+
Returns:
|
226
|
+
A list of custom filters.
|
227
|
+
"""
|
228
|
+
custom_filters = super().get_custom_filters(table)
|
229
|
+
|
230
|
+
from sqlmodel import exists, select
|
231
|
+
|
232
|
+
from zenml.zen_stores.schemas import (
|
233
|
+
TagResourceSchema,
|
234
|
+
TagSchema,
|
235
|
+
)
|
236
|
+
|
237
|
+
if self.resource_type:
|
238
|
+
# Filter for tags that have at least one association with the specified resource type
|
239
|
+
resource_type_filter = exists(
|
240
|
+
select(TagResourceSchema).where(
|
241
|
+
TagResourceSchema.tag_id == TagSchema.id,
|
242
|
+
TagResourceSchema.resource_type
|
243
|
+
== self.resource_type.value,
|
244
|
+
)
|
245
|
+
)
|
246
|
+
custom_filters.append(resource_type_filter)
|
247
|
+
|
248
|
+
return custom_filters
|
zenml/models/v2/core/trigger.py
CHANGED
@@ -33,12 +33,12 @@ from zenml.constants import STR_FIELD_MAX_LENGTH
|
|
33
33
|
from zenml.models.v2.base.base import BaseUpdate
|
34
34
|
from zenml.models.v2.base.page import Page
|
35
35
|
from zenml.models.v2.base.scoped import (
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
ProjectScopedFilter,
|
37
|
+
ProjectScopedRequest,
|
38
|
+
ProjectScopedResponse,
|
39
|
+
ProjectScopedResponseBody,
|
40
|
+
ProjectScopedResponseMetadata,
|
41
|
+
ProjectScopedResponseResources,
|
42
42
|
)
|
43
43
|
from zenml.models.v2.core.trigger_execution import TriggerExecutionResponse
|
44
44
|
|
@@ -57,7 +57,7 @@ if TYPE_CHECKING:
|
|
57
57
|
# ------------------ Request Model ------------------
|
58
58
|
|
59
59
|
|
60
|
-
class TriggerRequest(
|
60
|
+
class TriggerRequest(ProjectScopedRequest):
|
61
61
|
"""Model for creating a new trigger."""
|
62
62
|
|
63
63
|
name: str = Field(
|
@@ -145,7 +145,7 @@ class TriggerUpdate(BaseUpdate):
|
|
145
145
|
# ------------------ Response Model ------------------
|
146
146
|
|
147
147
|
|
148
|
-
class TriggerResponseBody(
|
148
|
+
class TriggerResponseBody(ProjectScopedResponseBody):
|
149
149
|
"""Response body for triggers."""
|
150
150
|
|
151
151
|
action_flavor: str = Field(
|
@@ -172,7 +172,7 @@ class TriggerResponseBody(WorkspaceScopedResponseBody):
|
|
172
172
|
)
|
173
173
|
|
174
174
|
|
175
|
-
class TriggerResponseMetadata(
|
175
|
+
class TriggerResponseMetadata(ProjectScopedResponseMetadata):
|
176
176
|
"""Response metadata for triggers."""
|
177
177
|
|
178
178
|
description: str = Field(
|
@@ -192,7 +192,7 @@ class TriggerResponseMetadata(WorkspaceScopedResponseMetadata):
|
|
192
192
|
)
|
193
193
|
|
194
194
|
|
195
|
-
class TriggerResponseResources(
|
195
|
+
class TriggerResponseResources(ProjectScopedResponseResources):
|
196
196
|
"""Class for all resource models associated with the trigger entity."""
|
197
197
|
|
198
198
|
action: "ActionResponse" = Field(
|
@@ -209,7 +209,7 @@ class TriggerResponseResources(WorkspaceScopedResponseResources):
|
|
209
209
|
|
210
210
|
|
211
211
|
class TriggerResponse(
|
212
|
-
|
212
|
+
ProjectScopedResponse[
|
213
213
|
TriggerResponseBody, TriggerResponseMetadata, TriggerResponseResources
|
214
214
|
]
|
215
215
|
):
|
@@ -324,11 +324,11 @@ class TriggerResponse(
|
|
324
324
|
# ------------------ Filter Model ------------------
|
325
325
|
|
326
326
|
|
327
|
-
class TriggerFilter(
|
327
|
+
class TriggerFilter(ProjectScopedFilter):
|
328
328
|
"""Model to enable advanced filtering of all triggers."""
|
329
329
|
|
330
330
|
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
|
331
|
-
*
|
331
|
+
*ProjectScopedFilter.FILTER_EXCLUDE_FIELDS,
|
332
332
|
"action_flavor",
|
333
333
|
"action_subtype",
|
334
334
|
"event_source_flavor",
|
@@ -27,7 +27,7 @@ from zenml.models.v2.base.base import (
|
|
27
27
|
BaseDatedResponseBody,
|
28
28
|
BaseResponseResources,
|
29
29
|
)
|
30
|
-
from zenml.models.v2.base.scoped import
|
30
|
+
from zenml.models.v2.base.scoped import ProjectScopedFilter
|
31
31
|
|
32
32
|
if TYPE_CHECKING:
|
33
33
|
from zenml.models.v2.core.trigger import TriggerResponse
|
@@ -109,7 +109,7 @@ class TriggerExecutionResponse(
|
|
109
109
|
# ------------------ Filter Model ------------------
|
110
110
|
|
111
111
|
|
112
|
-
class TriggerExecutionFilter(
|
112
|
+
class TriggerExecutionFilter(ProjectScopedFilter):
|
113
113
|
"""Model to enable advanced filtering of all trigger executions."""
|
114
114
|
|
115
115
|
trigger_id: Optional[Union[UUID, str]] = Field(
|
zenml/models/v2/core/user.py
CHANGED
@@ -81,10 +81,6 @@ class UserBase(BaseModel):
|
|
81
81
|
default=None,
|
82
82
|
title="The metadata associated with the user.",
|
83
83
|
)
|
84
|
-
default_workspace_id: Optional[UUID] = Field(
|
85
|
-
default=None,
|
86
|
-
title="The default workspace ID for the user.",
|
87
|
-
)
|
88
84
|
|
89
85
|
@classmethod
|
90
86
|
def _get_crypt_context(cls) -> "CryptContext":
|
@@ -283,10 +279,6 @@ class UserResponseBody(BaseDatedResponseBody):
|
|
283
279
|
is_admin: bool = Field(
|
284
280
|
title="Whether the account is an administrator.",
|
285
281
|
)
|
286
|
-
default_workspace_id: Optional[UUID] = Field(
|
287
|
-
default=None,
|
288
|
-
title="The default workspace ID for the user.",
|
289
|
-
)
|
290
282
|
|
291
283
|
|
292
284
|
class UserResponseMetadata(BaseResponseMetadata):
|
@@ -403,15 +395,6 @@ class UserResponse(
|
|
403
395
|
"""
|
404
396
|
return self.get_body().is_admin
|
405
397
|
|
406
|
-
@property
|
407
|
-
def default_workspace_id(self) -> Optional[UUID]:
|
408
|
-
"""The `default_workspace_id` property.
|
409
|
-
|
410
|
-
Returns:
|
411
|
-
the value of the property.
|
412
|
-
"""
|
413
|
-
return self.get_body().default_workspace_id
|
414
|
-
|
415
398
|
@property
|
416
399
|
def email(self) -> Optional[str]:
|
417
400
|
"""The `email` property.
|
@@ -131,16 +131,16 @@ class ServerModel(BaseModel):
|
|
131
131
|
"connected. Only set if the server is a ZenML Pro server.",
|
132
132
|
)
|
133
133
|
|
134
|
-
|
134
|
+
pro_workspace_id: Optional[UUID] = Field(
|
135
135
|
None,
|
136
|
-
title="The ID of the ZenML Pro
|
137
|
-
"Only set if the server is a ZenML Pro server.",
|
136
|
+
title="The ID of the ZenML Pro workspace to which the server is "
|
137
|
+
"connected. Only set if the server is a ZenML Pro server.",
|
138
138
|
)
|
139
139
|
|
140
|
-
|
140
|
+
pro_workspace_name: Optional[str] = Field(
|
141
141
|
None,
|
142
|
-
title="The name of the ZenML Pro
|
143
|
-
"Only set if the server is a ZenML Pro server.",
|
142
|
+
title="The name of the ZenML Pro workspace to which the server is "
|
143
|
+
"connected. Only set if the server is a ZenML Pro server.",
|
144
144
|
)
|
145
145
|
|
146
146
|
def is_local(self) -> bool:
|
@@ -20,8 +20,8 @@ from zenml.models.v2.base.base import (
|
|
20
20
|
)
|
21
21
|
|
22
22
|
|
23
|
-
class
|
24
|
-
"""
|
23
|
+
class ProjectStatistics(BaseZenModel):
|
24
|
+
"""Project statistics."""
|
25
25
|
|
26
26
|
pipelines: int = Field(
|
27
27
|
title="The number of pipelines.",
|
@@ -40,6 +40,6 @@ class ServerStatistics(BaseZenModel):
|
|
40
40
|
components: int = Field(
|
41
41
|
title="The number of components.",
|
42
42
|
)
|
43
|
-
|
44
|
-
title="The number of
|
43
|
+
projects: int = Field(
|
44
|
+
title="The number of projects.",
|
45
45
|
)
|
@@ -34,7 +34,7 @@ def generate_cache_key(
|
|
34
34
|
step: "Step",
|
35
35
|
input_artifact_ids: Dict[str, "UUID"],
|
36
36
|
artifact_store: "BaseArtifactStore",
|
37
|
-
|
37
|
+
project_id: "UUID",
|
38
38
|
) -> str:
|
39
39
|
"""Generates a cache key for a step run.
|
40
40
|
|
@@ -42,7 +42,7 @@ def generate_cache_key(
|
|
42
42
|
runs are identical and can be cached.
|
43
43
|
|
44
44
|
The cache key is a MD5 hash of:
|
45
|
-
- the
|
45
|
+
- the project ID,
|
46
46
|
- the artifact store ID and path,
|
47
47
|
- the source code that defines the step,
|
48
48
|
- the parameters of the step,
|
@@ -55,15 +55,15 @@ def generate_cache_key(
|
|
55
55
|
step: The step to generate the cache key for.
|
56
56
|
input_artifact_ids: The input artifact IDs for the step.
|
57
57
|
artifact_store: The artifact store of the active stack.
|
58
|
-
|
58
|
+
project_id: The ID of the active project.
|
59
59
|
|
60
60
|
Returns:
|
61
61
|
A cache key.
|
62
62
|
"""
|
63
63
|
hash_ = hashlib.md5() # nosec
|
64
64
|
|
65
|
-
#
|
66
|
-
hash_.update(
|
65
|
+
# Project ID
|
66
|
+
hash_.update(project_id.bytes)
|
67
67
|
|
68
68
|
# Artifact store ID and path
|
69
69
|
hash_.update(artifact_store.id.bytes)
|
@@ -106,7 +106,7 @@ def get_cached_step_run(cache_key: str) -> Optional["StepRunResponse"]:
|
|
106
106
|
"""If a given step can be cached, get the corresponding existing step run.
|
107
107
|
|
108
108
|
A step run can be cached if there is an existing step run in the same
|
109
|
-
|
109
|
+
project which has the same cache key and was successfully executed.
|
110
110
|
|
111
111
|
Args:
|
112
112
|
cache_key: The cache key of the step.
|
@@ -117,7 +117,7 @@ def get_cached_step_run(cache_key: str) -> Optional["StepRunResponse"]:
|
|
117
117
|
client = Client()
|
118
118
|
|
119
119
|
cache_candidates = client.list_run_steps(
|
120
|
-
|
120
|
+
project=client.active_project.id,
|
121
121
|
cache_key=cache_key,
|
122
122
|
status=ExecutionStatus.COMPLETED,
|
123
123
|
sort_by=f"{SorterOps.DESCENDING}:created",
|
@@ -319,7 +319,7 @@ class StepLauncher:
|
|
319
319
|
pipeline_run = PipelineRunRequest(
|
320
320
|
name=run_name,
|
321
321
|
orchestrator_run_id=self._orchestrator_run_id,
|
322
|
-
|
322
|
+
project=client.active_project.id,
|
323
323
|
deployment=self._deployment.id,
|
324
324
|
pipeline=(
|
325
325
|
self._deployment.pipeline.id
|
@@ -75,7 +75,7 @@ class StepRunRequestFactory:
|
|
75
75
|
pipeline_run_id=self.pipeline_run.id,
|
76
76
|
status=ExecutionStatus.RUNNING,
|
77
77
|
start_time=utc_now(),
|
78
|
-
|
78
|
+
project=Client().active_project.id,
|
79
79
|
)
|
80
80
|
|
81
81
|
def populate_request(self, request: StepRunRequest) -> None:
|
@@ -102,7 +102,7 @@ class StepRunRequestFactory:
|
|
102
102
|
step=step,
|
103
103
|
input_artifact_ids=input_artifact_ids,
|
104
104
|
artifact_store=self.stack.artifact_store,
|
105
|
-
|
105
|
+
project_id=Client().active_project.id,
|
106
106
|
)
|
107
107
|
request.cache_key = cache_key
|
108
108
|
|
@@ -344,7 +344,7 @@ def log_model_version_dashboard_url(
|
|
344
344
|
) -> None:
|
345
345
|
"""Log the dashboard URL for a model version.
|
346
346
|
|
347
|
-
If the current server is not a ZenML Pro
|
347
|
+
If the current server is not a ZenML Pro workspace, a fallback message is
|
348
348
|
logged instead.
|
349
349
|
|
350
350
|
Args:
|
zenml/orchestrators/utils.py
CHANGED
@@ -23,8 +23,8 @@ from zenml.config.global_config import (
|
|
23
23
|
GlobalConfiguration,
|
24
24
|
)
|
25
25
|
from zenml.constants import (
|
26
|
+
ENV_ZENML_ACTIVE_PROJECT_ID,
|
26
27
|
ENV_ZENML_ACTIVE_STACK_ID,
|
27
|
-
ENV_ZENML_ACTIVE_WORKSPACE_ID,
|
28
28
|
ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING,
|
29
29
|
ENV_ZENML_PIPELINE_RUN_API_TOKEN_EXPIRATION,
|
30
30
|
ENV_ZENML_SERVER,
|
@@ -211,13 +211,13 @@ def get_config_environment_vars(
|
|
211
211
|
# in the pipeline run environment
|
212
212
|
environment_vars[ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING] = "true"
|
213
213
|
|
214
|
-
# Make sure to use the correct active stack/
|
214
|
+
# Make sure to use the correct active stack/project which might come
|
215
215
|
# from a .zen repository and not the global config
|
216
216
|
environment_vars[ENV_ZENML_ACTIVE_STACK_ID] = str(
|
217
217
|
Client().active_stack_model.id
|
218
218
|
)
|
219
|
-
environment_vars[
|
220
|
-
Client().
|
219
|
+
environment_vars[ENV_ZENML_ACTIVE_PROJECT_ID] = str(
|
220
|
+
Client().active_project.id
|
221
221
|
)
|
222
222
|
|
223
223
|
return environment_vars
|
zenml/pipelines/build_utils.py
CHANGED
@@ -215,7 +215,7 @@ def reuse_or_create_pipeline_build(
|
|
215
215
|
build_model = Client().zen_store.get_build(build_id=build)
|
216
216
|
else:
|
217
217
|
build_request = PipelineBuildRequest(
|
218
|
-
|
218
|
+
project=Client().active_project.id,
|
219
219
|
stack=Client().active_stack_model.id,
|
220
220
|
pipeline=pipeline_id,
|
221
221
|
**build.model_dump(),
|
@@ -418,7 +418,7 @@ def create_pipeline_build(
|
|
418
418
|
)
|
419
419
|
stack_checksum = compute_stack_checksum(stack=stack_model)
|
420
420
|
build_request = PipelineBuildRequest(
|
421
|
-
|
421
|
+
project=client.active_project.id,
|
422
422
|
stack=stack_model.id,
|
423
423
|
pipeline=pipeline_id,
|
424
424
|
is_local=is_local,
|
@@ -684,7 +684,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
684
684
|
components = Client().active_stack_model.components
|
685
685
|
orchestrator = components[StackComponentType.ORCHESTRATOR][0]
|
686
686
|
schedule_model = ScheduleRequest(
|
687
|
-
|
687
|
+
project=Client().active_project.id,
|
688
688
|
pipeline_id=pipeline_id,
|
689
689
|
orchestrator_id=orchestrator.id,
|
690
690
|
name=schedule_name,
|
@@ -770,7 +770,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
770
770
|
code_path = code_utils.upload_code_if_necessary(code_archive)
|
771
771
|
|
772
772
|
request = PipelineDeploymentRequest(
|
773
|
-
|
773
|
+
project=Client().active_project.id,
|
774
774
|
stack=stack.id,
|
775
775
|
pipeline=pipeline_id,
|
776
776
|
build=build_id,
|
@@ -1013,7 +1013,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
1013
1013
|
for component_type, component in stack.components.items()
|
1014
1014
|
}
|
1015
1015
|
return {
|
1016
|
-
"
|
1016
|
+
"project_id": deployment.project.id,
|
1017
1017
|
"store_type": Client().zen_store.type.value,
|
1018
1018
|
**stack_metadata,
|
1019
1019
|
"total_steps": len(self.invocations),
|
@@ -1094,7 +1094,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
1094
1094
|
return _get()
|
1095
1095
|
except RuntimeError:
|
1096
1096
|
request = PipelineRequest(
|
1097
|
-
|
1097
|
+
project=client.active_project.id,
|
1098
1098
|
name=self.name,
|
1099
1099
|
)
|
1100
1100
|
|
@@ -1233,7 +1233,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
1233
1233
|
return id_
|
1234
1234
|
|
1235
1235
|
if not allow_suffix:
|
1236
|
-
raise RuntimeError("Duplicate step ID")
|
1236
|
+
raise RuntimeError(f"Duplicate step ID `{id_}`")
|
1237
1237
|
|
1238
1238
|
for index in range(2, 10000):
|
1239
1239
|
id_ = f"{base_id}_{index}"
|
zenml/pipelines/run_utils.py
CHANGED
@@ -81,7 +81,7 @@ def create_placeholder_run(
|
|
81
81
|
# running.
|
82
82
|
start_time=start_time,
|
83
83
|
orchestrator_run_id=None,
|
84
|
-
|
84
|
+
project=deployment.project.id,
|
85
85
|
deployment=deployment.id,
|
86
86
|
pipeline=deployment.pipeline.id if deployment.pipeline else None,
|
87
87
|
status=ExecutionStatus.INITIALIZING,
|
@@ -705,7 +705,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
|
|
705
705
|
|
706
706
|
def to_model(
|
707
707
|
self,
|
708
|
-
workspace: UUID,
|
709
708
|
name: Optional[str] = None,
|
710
709
|
description: str = "",
|
711
710
|
labels: Optional[Dict[str, str]] = None,
|
@@ -714,7 +713,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
|
|
714
713
|
|
715
714
|
Args:
|
716
715
|
name: The name of the connector.
|
717
|
-
workspace: The ID of the workspace that the connector belongs to.
|
718
716
|
description: The description of the connector.
|
719
717
|
labels: The labels of the connector.
|
720
718
|
|
@@ -737,7 +735,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
|
|
737
735
|
connector_type=spec.connector_type,
|
738
736
|
name=name,
|
739
737
|
description=description,
|
740
|
-
workspace=workspace,
|
741
738
|
auth_method=self.auth_method,
|
742
739
|
expires_at=self.expires_at,
|
743
740
|
expires_skew_tolerance=self.expires_skew_tolerance,
|
@@ -184,7 +184,6 @@ def get_resources_options_from_resource_model_for_full_stack(
|
|
184
184
|
else:
|
185
185
|
resource_model = zen_store.verify_service_connector_config(
|
186
186
|
service_connector=ServiceConnectorRequest(
|
187
|
-
workspace=client.active_workspace.id,
|
188
187
|
name="fake",
|
189
188
|
connector_type=connector_details.type,
|
190
189
|
auth_method=connector_details.auth_method,
|
zenml/stack/stack.py
CHANGED
zenml/steps/base_step.py
CHANGED
@@ -432,7 +432,9 @@ class BaseStep:
|
|
432
432
|
self,
|
433
433
|
*args: Any,
|
434
434
|
id: Optional[str] = None,
|
435
|
-
after: Union[
|
435
|
+
after: Union[
|
436
|
+
str, StepArtifact, Sequence[Union[str, StepArtifact]], None
|
437
|
+
] = None,
|
436
438
|
**kwargs: Any,
|
437
439
|
) -> Any:
|
438
440
|
"""Handle a call of the step.
|
@@ -497,8 +499,14 @@ class BaseStep:
|
|
497
499
|
}
|
498
500
|
if isinstance(after, str):
|
499
501
|
upstream_steps.add(after)
|
502
|
+
elif isinstance(after, StepArtifact):
|
503
|
+
upstream_steps.add(after.invocation_id)
|
500
504
|
elif isinstance(after, Sequence):
|
501
|
-
|
505
|
+
for item in after:
|
506
|
+
if isinstance(item, str):
|
507
|
+
upstream_steps.add(item)
|
508
|
+
elif isinstance(item, StepArtifact):
|
509
|
+
upstream_steps.add(item.invocation_id)
|
502
510
|
|
503
511
|
invocation_id = Pipeline.ACTIVE_PIPELINE.add_step_invocation(
|
504
512
|
step=self,
|
zenml/utils/dashboard_utils.py
CHANGED
@@ -33,7 +33,7 @@ logger = get_logger(__name__)
|
|
33
33
|
|
34
34
|
|
35
35
|
def get_cloud_dashboard_url() -> Optional[str]:
|
36
|
-
"""Get the base url of the cloud dashboard if the server is a
|
36
|
+
"""Get the base url of the cloud dashboard if the server is a ZenML Pro workspace.
|
37
37
|
|
38
38
|
Returns:
|
39
39
|
The base url of the cloud dashboard.
|
zenml/utils/tag_utils.py
CHANGED
@@ -379,18 +379,6 @@ def add_tags(
|
|
379
379
|
else:
|
380
380
|
tag_model = client.create_tag(name=tag)
|
381
381
|
|
382
|
-
if tag_model.exclusive and resource_type not in [
|
383
|
-
TaggableResourceTypes.PIPELINE_RUN,
|
384
|
-
TaggableResourceTypes.ARTIFACT_VERSION,
|
385
|
-
TaggableResourceTypes.RUN_TEMPLATE,
|
386
|
-
]:
|
387
|
-
logger.warning(
|
388
|
-
"The tag will be added, however, please keep in mind that "
|
389
|
-
"the functionality of having exclusive tags is only "
|
390
|
-
"applicable for pipeline runs, artifact versions and run "
|
391
|
-
f"templates, not {resource_type.value}s."
|
392
|
-
)
|
393
|
-
|
394
382
|
if resource_id:
|
395
383
|
client.attach_tag(
|
396
384
|
tag_name_or_id=tag_model.name,
|
zenml/zen_server/cloud_utils.py
CHANGED
@@ -267,6 +267,6 @@ def cloud_connection() -> ZenMLCloudConnection:
|
|
267
267
|
return _cloud_connection
|
268
268
|
|
269
269
|
|
270
|
-
def
|
271
|
-
"""Send a
|
272
|
-
cloud_connection().patch("/
|
270
|
+
def send_pro_workspace_status_update() -> None:
|
271
|
+
"""Send a workspace status update to the Cloud API."""
|
272
|
+
cloud_connection().patch("/workspace_status")
|
@@ -20,7 +20,7 @@ from zenml.zen_server.utils import feature_gate, server_config
|
|
20
20
|
|
21
21
|
|
22
22
|
def check_entitlement(resource_type: ResourceType) -> None:
|
23
|
-
"""Queries the feature gate to see if the operation falls within the
|
23
|
+
"""Queries the feature gate to see if the operation falls within the Pro workspaces entitlements.
|
24
24
|
|
25
25
|
Raises an exception if the user is not entitled to create an instance of the
|
26
26
|
resource. Otherwise, simply returns.
|
@@ -110,7 +110,7 @@ class ZenMLCloudFeatureGateInterface(FeatureGateInterface):
|
|
110
110
|
feature=resource,
|
111
111
|
total=1 if not is_decrement else -1,
|
112
112
|
metadata={
|
113
|
-
"
|
113
|
+
"workspace_id": str(server_config.get_external_server_id()),
|
114
114
|
"resource_id": str(resource_id),
|
115
115
|
},
|
116
116
|
).model_dump()
|