zenml-nightly 0.58.2.dev20240624__py3-none-any.whl → 0.58.2.dev20240625__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/actions/base_action.py +177 -174
- zenml/actions/pipeline_run/pipeline_run_action.py +28 -23
- zenml/client.py +226 -55
- zenml/config/compiler.py +10 -9
- zenml/config/docker_settings.py +25 -9
- zenml/constants.py +1 -1
- zenml/event_hub/base_event_hub.py +5 -5
- zenml/event_hub/event_hub.py +15 -6
- zenml/event_sources/base_event.py +0 -11
- zenml/event_sources/base_event_source.py +7 -0
- zenml/event_sources/webhooks/base_webhook_event_source.py +1 -4
- zenml/exceptions.py +4 -0
- zenml/hooks/hook_validators.py +2 -3
- zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +3 -3
- zenml/integrations/mlflow/__init__.py +1 -1
- zenml/models/__init__.py +17 -0
- zenml/models/v2/core/action.py +276 -0
- zenml/models/v2/core/trigger.py +182 -141
- zenml/new/pipelines/pipeline.py +13 -3
- zenml/new/pipelines/pipeline_decorator.py +1 -2
- zenml/new/pipelines/run_utils.py +1 -12
- zenml/new/steps/step_decorator.py +2 -3
- zenml/pipelines/base_pipeline.py +0 -2
- zenml/pipelines/pipeline_decorator.py +1 -2
- zenml/steps/base_step.py +1 -2
- zenml/steps/step_decorator.py +1 -2
- zenml/types.py +10 -1
- zenml/utils/pipeline_docker_image_builder.py +20 -5
- zenml/zen_server/rbac/models.py +1 -0
- zenml/zen_server/rbac/utils.py +22 -1
- zenml/zen_server/routers/actions_endpoints.py +324 -0
- zenml/zen_server/routers/triggers_endpoints.py +30 -158
- zenml/zen_server/zen_server_api.py +2 -0
- zenml/zen_stores/migrations/versions/25155145c545_separate_actions_and_triggers.py +228 -0
- zenml/zen_stores/rest_zen_store.py +103 -4
- zenml/zen_stores/schemas/__init__.py +2 -0
- zenml/zen_stores/schemas/action_schemas.py +192 -0
- zenml/zen_stores/schemas/trigger_schemas.py +43 -50
- zenml/zen_stores/schemas/user_schemas.py +10 -2
- zenml/zen_stores/schemas/workspace_schemas.py +5 -0
- zenml/zen_stores/sql_zen_store.py +240 -30
- zenml/zen_stores/zen_store_interface.py +85 -0
- {zenml_nightly-0.58.2.dev20240624.dist-info → zenml_nightly-0.58.2.dev20240625.dist-info}/METADATA +1 -1
- {zenml_nightly-0.58.2.dev20240624.dist-info → zenml_nightly-0.58.2.dev20240625.dist-info}/RECORD +48 -44
- {zenml_nightly-0.58.2.dev20240624.dist-info → zenml_nightly-0.58.2.dev20240625.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.58.2.dev20240624.dist-info → zenml_nightly-0.58.2.dev20240625.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.58.2.dev20240624.dist-info → zenml_nightly-0.58.2.dev20240625.dist-info}/entry_points.txt +0 -0
zenml/event_hub/event_hub.py
CHANGED
@@ -14,7 +14,9 @@
|
|
14
14
|
"""Base class for all the Event Hub."""
|
15
15
|
|
16
16
|
from functools import partial
|
17
|
-
from typing import
|
17
|
+
from typing import List
|
18
|
+
|
19
|
+
from pydantic import ValidationError
|
18
20
|
|
19
21
|
from zenml import EventSourceResponse
|
20
22
|
from zenml.enums import PluginType
|
@@ -35,9 +37,6 @@ from zenml.zen_server.utils import plugin_flavor_registry
|
|
35
37
|
|
36
38
|
logger = get_logger(__name__)
|
37
39
|
|
38
|
-
if TYPE_CHECKING:
|
39
|
-
pass
|
40
|
-
|
41
40
|
|
42
41
|
class InternalEventHub(BaseEventHub):
|
43
42
|
"""Internal in-server event hub implementation.
|
@@ -158,9 +157,19 @@ class InternalEventHub(BaseEventHub):
|
|
158
157
|
|
159
158
|
assert issubclass(plugin_flavor, BaseEventSourceFlavor)
|
160
159
|
|
161
|
-
# Get the filter class from the plugin flavor class
|
162
160
|
event_filter_config_class = plugin_flavor.EVENT_FILTER_CONFIG_CLASS
|
163
|
-
|
161
|
+
try:
|
162
|
+
event_filter = event_filter_config_class(
|
163
|
+
**trigger.event_filter if trigger.event_filter else {}
|
164
|
+
)
|
165
|
+
except ValidationError:
|
166
|
+
logger.exception(
|
167
|
+
f"Could not instantiate event filter config class for "
|
168
|
+
f"event source {event_source.id}. Skipping trigger "
|
169
|
+
f"{trigger.id}."
|
170
|
+
)
|
171
|
+
continue
|
172
|
+
|
164
173
|
if event_filter.event_matches_filter(event=event):
|
165
174
|
trigger_list.append(trigger)
|
166
175
|
|
@@ -13,19 +13,8 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Base implementation for events."""
|
15
15
|
|
16
|
-
from typing import (
|
17
|
-
TYPE_CHECKING,
|
18
|
-
)
|
19
|
-
|
20
16
|
from pydantic import BaseModel
|
21
17
|
|
22
|
-
from zenml.logger import get_logger
|
23
|
-
|
24
|
-
if TYPE_CHECKING:
|
25
|
-
pass
|
26
|
-
|
27
|
-
logger = get_logger(__name__)
|
28
|
-
|
29
18
|
# -------------------- Event Models -----------------------------------
|
30
19
|
|
31
20
|
|
@@ -449,6 +449,13 @@ class BaseEventSourceHandler(BasePlugin, ABC):
|
|
449
449
|
event: The event to dispatch.
|
450
450
|
event_source: The event source that produced the event.
|
451
451
|
"""
|
452
|
+
if not event_source.is_active:
|
453
|
+
logger.debug(
|
454
|
+
f"Event source {event_source.id} is not active. Skipping event "
|
455
|
+
f"dispatch."
|
456
|
+
)
|
457
|
+
return
|
458
|
+
|
452
459
|
self.event_hub.publish_event(
|
453
460
|
event=event,
|
454
461
|
event_source=event_source,
|
@@ -17,7 +17,7 @@ import hashlib
|
|
17
17
|
import hmac
|
18
18
|
import json
|
19
19
|
from abc import ABC, abstractmethod
|
20
|
-
from typing import
|
20
|
+
from typing import Any, ClassVar, Dict, Optional, Type
|
21
21
|
|
22
22
|
from zenml.enums import PluginSubType
|
23
23
|
from zenml.event_sources.base_event import BaseEvent
|
@@ -33,9 +33,6 @@ from zenml.models import EventSourceResponse
|
|
33
33
|
|
34
34
|
logger = get_logger(__name__)
|
35
35
|
|
36
|
-
if TYPE_CHECKING:
|
37
|
-
pass
|
38
|
-
|
39
36
|
|
40
37
|
# -------------------- Event Models -----------------------------------
|
41
38
|
|
zenml/exceptions.py
CHANGED
@@ -197,6 +197,10 @@ class EntityExistsError(ZenMLBaseException):
|
|
197
197
|
"""Raised when trying to register an entity that already exists."""
|
198
198
|
|
199
199
|
|
200
|
+
class ActionExistsError(EntityExistsError):
|
201
|
+
"""Raised when registering an action with a name that already exists."""
|
202
|
+
|
203
|
+
|
200
204
|
class TriggerExistsError(EntityExistsError):
|
201
205
|
"""Raised when registering a trigger with name that already exists."""
|
202
206
|
|
zenml/hooks/hook_validators.py
CHANGED
@@ -14,14 +14,13 @@
|
|
14
14
|
"""Validation functions for hooks."""
|
15
15
|
|
16
16
|
import inspect
|
17
|
-
from
|
18
|
-
from typing import TYPE_CHECKING, Union
|
17
|
+
from typing import TYPE_CHECKING
|
19
18
|
|
20
19
|
from zenml.config.source import Source
|
21
20
|
from zenml.utils import source_utils
|
22
21
|
|
23
22
|
if TYPE_CHECKING:
|
24
|
-
|
23
|
+
from zenml.types import HookSpecification
|
25
24
|
|
26
25
|
|
27
26
|
def resolve_and_validate_hook(hook: "HookSpecification") -> Source:
|
@@ -152,9 +152,9 @@ class BitbucketEvent(BaseEvent):
|
|
152
152
|
class BitbucketWebhookEventFilterConfiguration(WebhookEventFilterConfig):
|
153
153
|
"""Configuration for Bitbucket event filters."""
|
154
154
|
|
155
|
-
repo: Optional[str]
|
156
|
-
branch: Optional[str]
|
157
|
-
event_type: Optional[BitbucketEventType]
|
155
|
+
repo: Optional[str] = None
|
156
|
+
branch: Optional[str] = None
|
157
|
+
event_type: Optional[BitbucketEventType] = None
|
158
158
|
|
159
159
|
def event_matches_filter(self, event: BaseEvent) -> bool:
|
160
160
|
"""Checks the filter against the inbound event.
|
zenml/models/__init__.py
CHANGED
@@ -51,6 +51,15 @@ from zenml.models.v2.base.filter import (
|
|
51
51
|
from zenml.models.v2.base.page import Page
|
52
52
|
|
53
53
|
# V2 Core
|
54
|
+
from zenml.models.v2.core.action import (
|
55
|
+
ActionFilter,
|
56
|
+
ActionRequest,
|
57
|
+
ActionResponse,
|
58
|
+
ActionResponseBody,
|
59
|
+
ActionResponseMetadata,
|
60
|
+
ActionResponseResources,
|
61
|
+
ActionUpdate,
|
62
|
+
)
|
54
63
|
from zenml.models.v2.core.action_flavor import (
|
55
64
|
ActionFlavorResponse,
|
56
65
|
ActionFlavorResponseBody,
|
@@ -381,6 +390,7 @@ from zenml.models.v2.core.server_settings import (
|
|
381
390
|
# ----------------------------- Forward References -----------------------------
|
382
391
|
|
383
392
|
# V2
|
393
|
+
ActionResponseResources.model_rebuild()
|
384
394
|
APIKeyResponseBody.model_rebuild()
|
385
395
|
ArtifactVersionRequest.model_rebuild()
|
386
396
|
ArtifactVersionResponseBody.model_rebuild()
|
@@ -470,6 +480,13 @@ __all__ = [
|
|
470
480
|
"UUIDFilter",
|
471
481
|
"Page",
|
472
482
|
# V2 Core
|
483
|
+
"ActionFilter",
|
484
|
+
"ActionRequest",
|
485
|
+
"ActionResponse",
|
486
|
+
"ActionResponseBody",
|
487
|
+
"ActionResponseMetadata",
|
488
|
+
"ActionResponseResources",
|
489
|
+
"ActionUpdate",
|
473
490
|
"ActionFlavorResponse",
|
474
491
|
"ActionFlavorResponseBody",
|
475
492
|
"ActionFlavorResponseMetadata",
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2024. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Collection of all models concerning actions."""
|
15
|
+
|
16
|
+
import copy
|
17
|
+
from typing import (
|
18
|
+
TYPE_CHECKING,
|
19
|
+
Any,
|
20
|
+
Dict,
|
21
|
+
Optional,
|
22
|
+
TypeVar,
|
23
|
+
)
|
24
|
+
from uuid import UUID
|
25
|
+
|
26
|
+
from pydantic import Field
|
27
|
+
|
28
|
+
from zenml.constants import STR_FIELD_MAX_LENGTH
|
29
|
+
from zenml.enums import PluginSubType
|
30
|
+
from zenml.models.v2.base.base import BaseUpdate
|
31
|
+
from zenml.models.v2.base.scoped import (
|
32
|
+
WorkspaceScopedFilter,
|
33
|
+
WorkspaceScopedRequest,
|
34
|
+
WorkspaceScopedResponse,
|
35
|
+
WorkspaceScopedResponseBody,
|
36
|
+
WorkspaceScopedResponseMetadata,
|
37
|
+
WorkspaceScopedResponseResources,
|
38
|
+
)
|
39
|
+
from zenml.models.v2.core.user import UserResponse
|
40
|
+
|
41
|
+
if TYPE_CHECKING:
|
42
|
+
from zenml.zen_stores.schemas import BaseSchema
|
43
|
+
|
44
|
+
AnySchema = TypeVar("AnySchema", bound=BaseSchema)
|
45
|
+
|
46
|
+
|
47
|
+
# ------------------ Request Model ------------------
|
48
|
+
|
49
|
+
|
50
|
+
class ActionRequest(WorkspaceScopedRequest):
|
51
|
+
"""Model for creating a new action."""
|
52
|
+
|
53
|
+
name: str = Field(
|
54
|
+
title="The name of the action.", max_length=STR_FIELD_MAX_LENGTH
|
55
|
+
)
|
56
|
+
description: str = Field(
|
57
|
+
default="",
|
58
|
+
title="The description of the action",
|
59
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
60
|
+
)
|
61
|
+
flavor: str = Field(
|
62
|
+
title="The flavor of the action.",
|
63
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
64
|
+
)
|
65
|
+
plugin_subtype: PluginSubType = Field(
|
66
|
+
title="The subtype of the action.",
|
67
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
68
|
+
)
|
69
|
+
configuration: Dict[str, Any] = Field(
|
70
|
+
title="The configuration for the action.",
|
71
|
+
)
|
72
|
+
service_account_id: UUID = Field(
|
73
|
+
title="The service account that is used to execute the action.",
|
74
|
+
)
|
75
|
+
auth_window: Optional[int] = Field(
|
76
|
+
default=None,
|
77
|
+
title="The time window in minutes for which the service account is "
|
78
|
+
"authorized to execute the action. Set this to 0 to authorize the "
|
79
|
+
"service account indefinitely (not recommended). If not set, a "
|
80
|
+
"default value defined for each individual action type is used.",
|
81
|
+
)
|
82
|
+
|
83
|
+
|
84
|
+
# ------------------ Update Model ------------------
|
85
|
+
|
86
|
+
|
87
|
+
class ActionUpdate(BaseUpdate):
|
88
|
+
"""Update model for actions."""
|
89
|
+
|
90
|
+
name: Optional[str] = Field(
|
91
|
+
default=None,
|
92
|
+
title="The new name for the action.",
|
93
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
94
|
+
)
|
95
|
+
description: Optional[str] = Field(
|
96
|
+
default=None,
|
97
|
+
title="The new description for the action.",
|
98
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
99
|
+
)
|
100
|
+
configuration: Optional[Dict[str, Any]] = Field(
|
101
|
+
default=None,
|
102
|
+
title="The configuration for the action.",
|
103
|
+
)
|
104
|
+
service_account_id: Optional[UUID] = Field(
|
105
|
+
default=None,
|
106
|
+
title="The service account that is used to execute the action.",
|
107
|
+
)
|
108
|
+
auth_window: Optional[int] = Field(
|
109
|
+
default=None,
|
110
|
+
title="The time window in minutes for which the service account is "
|
111
|
+
"authorized to execute the action. Set this to 0 to authorize the "
|
112
|
+
"service account indefinitely (not recommended). If not set, a "
|
113
|
+
"default value defined for each individual action type is used.",
|
114
|
+
)
|
115
|
+
|
116
|
+
@classmethod
|
117
|
+
def from_response(cls, response: "ActionResponse") -> "ActionUpdate":
|
118
|
+
"""Create an update model from a response model.
|
119
|
+
|
120
|
+
Args:
|
121
|
+
response: The response model to create the update model from.
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
The update model.
|
125
|
+
"""
|
126
|
+
return ActionUpdate(
|
127
|
+
configuration=copy.deepcopy(response.configuration),
|
128
|
+
)
|
129
|
+
|
130
|
+
|
131
|
+
# ------------------ Response Model ------------------
|
132
|
+
|
133
|
+
|
134
|
+
class ActionResponseBody(WorkspaceScopedResponseBody):
|
135
|
+
"""Response body for actions."""
|
136
|
+
|
137
|
+
flavor: str = Field(
|
138
|
+
title="The flavor of the action.",
|
139
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
140
|
+
)
|
141
|
+
plugin_subtype: PluginSubType = Field(
|
142
|
+
title="The subtype of the action.",
|
143
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
144
|
+
)
|
145
|
+
|
146
|
+
|
147
|
+
class ActionResponseMetadata(WorkspaceScopedResponseMetadata):
|
148
|
+
"""Response metadata for actions."""
|
149
|
+
|
150
|
+
description: str = Field(
|
151
|
+
default="",
|
152
|
+
title="The description of the action.",
|
153
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
154
|
+
)
|
155
|
+
configuration: Dict[str, Any] = Field(
|
156
|
+
title="The configuration for the action.",
|
157
|
+
)
|
158
|
+
auth_window: int = Field(
|
159
|
+
title="The time window in minutes for which the service account is "
|
160
|
+
"authorized to execute the action."
|
161
|
+
)
|
162
|
+
|
163
|
+
|
164
|
+
class ActionResponseResources(WorkspaceScopedResponseResources):
|
165
|
+
"""Class for all resource models associated with the action entity."""
|
166
|
+
|
167
|
+
service_account: UserResponse = Field(
|
168
|
+
title="The service account that is used to execute the action.",
|
169
|
+
)
|
170
|
+
|
171
|
+
|
172
|
+
class ActionResponse(
|
173
|
+
WorkspaceScopedResponse[
|
174
|
+
ActionResponseBody, ActionResponseMetadata, ActionResponseResources
|
175
|
+
]
|
176
|
+
):
|
177
|
+
"""Response model for actions."""
|
178
|
+
|
179
|
+
name: str = Field(
|
180
|
+
title="The name of the action.",
|
181
|
+
max_length=STR_FIELD_MAX_LENGTH,
|
182
|
+
)
|
183
|
+
|
184
|
+
def get_hydrated_version(self) -> "ActionResponse":
|
185
|
+
"""Get the hydrated version of this action.
|
186
|
+
|
187
|
+
Returns:
|
188
|
+
An instance of the same entity with the metadata field attached.
|
189
|
+
"""
|
190
|
+
from zenml.client import Client
|
191
|
+
|
192
|
+
return Client().zen_store.get_action(self.id)
|
193
|
+
|
194
|
+
# Body and metadata properties
|
195
|
+
@property
|
196
|
+
def flavor(self) -> str:
|
197
|
+
"""The `flavor` property.
|
198
|
+
|
199
|
+
Returns:
|
200
|
+
the value of the property.
|
201
|
+
"""
|
202
|
+
return self.get_body().flavor
|
203
|
+
|
204
|
+
@property
|
205
|
+
def plugin_subtype(self) -> PluginSubType:
|
206
|
+
"""The `plugin_subtype` property.
|
207
|
+
|
208
|
+
Returns:
|
209
|
+
the value of the property.
|
210
|
+
"""
|
211
|
+
return self.get_body().plugin_subtype
|
212
|
+
|
213
|
+
@property
|
214
|
+
def description(self) -> str:
|
215
|
+
"""The `description` property.
|
216
|
+
|
217
|
+
Returns:
|
218
|
+
the value of the property.
|
219
|
+
"""
|
220
|
+
return self.get_metadata().description
|
221
|
+
|
222
|
+
@property
|
223
|
+
def auth_window(self) -> int:
|
224
|
+
"""The `auth_window` property.
|
225
|
+
|
226
|
+
Returns:
|
227
|
+
the value of the property.
|
228
|
+
"""
|
229
|
+
return self.get_metadata().auth_window
|
230
|
+
|
231
|
+
@property
|
232
|
+
def configuration(self) -> Dict[str, Any]:
|
233
|
+
"""The `configuration` property.
|
234
|
+
|
235
|
+
Returns:
|
236
|
+
the value of the property.
|
237
|
+
"""
|
238
|
+
return self.get_metadata().configuration
|
239
|
+
|
240
|
+
def set_configuration(self, configuration: Dict[str, Any]) -> None:
|
241
|
+
"""Set the `configuration` property.
|
242
|
+
|
243
|
+
Args:
|
244
|
+
configuration: The value to set.
|
245
|
+
"""
|
246
|
+
self.get_metadata().configuration = configuration
|
247
|
+
|
248
|
+
# Resource properties
|
249
|
+
@property
|
250
|
+
def service_account(self) -> "UserResponse":
|
251
|
+
"""The `service_account` property.
|
252
|
+
|
253
|
+
Returns:
|
254
|
+
the value of the property.
|
255
|
+
"""
|
256
|
+
return self.get_resources().service_account
|
257
|
+
|
258
|
+
|
259
|
+
# ------------------ Filter Model ------------------
|
260
|
+
|
261
|
+
|
262
|
+
class ActionFilter(WorkspaceScopedFilter):
|
263
|
+
"""Model to enable advanced filtering of all actions."""
|
264
|
+
|
265
|
+
name: Optional[str] = Field(
|
266
|
+
default=None,
|
267
|
+
description="Name of the action.",
|
268
|
+
)
|
269
|
+
flavor: Optional[str] = Field(
|
270
|
+
default=None,
|
271
|
+
title="The flavor of the action.",
|
272
|
+
)
|
273
|
+
plugin_subtype: Optional[str] = Field(
|
274
|
+
default=None,
|
275
|
+
title="The subtype of the action.",
|
276
|
+
)
|