zenml-nightly 0.58.2.dev20240622__py3-none-any.whl → 0.58.2.dev20240626__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/artifact_stores/base_artifact_store.py +7 -1
- zenml/artifacts/utils.py +13 -10
- zenml/cli/service_connectors.py +1 -0
- zenml/client.py +234 -58
- 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/integrations/s3/artifact_stores/s3_artifact_store.py +76 -3
- zenml/logging/step_logging.py +54 -51
- 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/stack/stack_component.py +4 -0
- 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.dev20240622.dist-info → zenml_nightly-0.58.2.dev20240626.dist-info}/METADATA +2 -2
- {zenml_nightly-0.58.2.dev20240622.dist-info → zenml_nightly-0.58.2.dev20240626.dist-info}/RECORD +54 -50
- {zenml_nightly-0.58.2.dev20240622.dist-info → zenml_nightly-0.58.2.dev20240626.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.58.2.dev20240622.dist-info → zenml_nightly-0.58.2.dev20240626.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.58.2.dev20240622.dist-info → zenml_nightly-0.58.2.dev20240626.dist-info}/entry_points.txt +0 -0
@@ -18,7 +18,6 @@ from uuid import UUID
|
|
18
18
|
from fastapi import APIRouter, Depends, Security
|
19
19
|
|
20
20
|
from zenml import TriggerRequest
|
21
|
-
from zenml.actions.base_action import BaseActionHandler
|
22
21
|
from zenml.constants import API, TRIGGER_EXECUTIONS, TRIGGERS, VERSION_1
|
23
22
|
from zenml.enums import PluginType
|
24
23
|
from zenml.event_sources.base_event_source import BaseEventSourceHandler
|
@@ -81,54 +80,11 @@ def list_triggers(
|
|
81
80
|
Returns:
|
82
81
|
All triggers.
|
83
82
|
"""
|
84
|
-
|
85
|
-
def list_triggers_fn(
|
86
|
-
filter_model: TriggerFilter,
|
87
|
-
) -> Page[TriggerResponse]:
|
88
|
-
"""List triggers through their associated plugins.
|
89
|
-
|
90
|
-
Args:
|
91
|
-
filter_model: Filter model used for pagination, sorting,
|
92
|
-
filtering.
|
93
|
-
|
94
|
-
Returns:
|
95
|
-
All triggers.
|
96
|
-
|
97
|
-
Raises:
|
98
|
-
ValueError: If the plugin for a trigger action is not a valid action
|
99
|
-
plugin.
|
100
|
-
"""
|
101
|
-
triggers = zen_store().list_triggers(
|
102
|
-
trigger_filter_model=filter_model, hydrate=hydrate
|
103
|
-
)
|
104
|
-
|
105
|
-
# Process the triggers through their associated plugins
|
106
|
-
for idx, trigger in enumerate(triggers.items):
|
107
|
-
action_handler = plugin_flavor_registry().get_plugin(
|
108
|
-
name=trigger.action_flavor,
|
109
|
-
_type=PluginType.ACTION,
|
110
|
-
subtype=trigger.action_subtype,
|
111
|
-
)
|
112
|
-
|
113
|
-
# Validate that the flavor and plugin_type correspond to an action
|
114
|
-
# handler implementation
|
115
|
-
if not isinstance(action_handler, BaseActionHandler):
|
116
|
-
raise ValueError(
|
117
|
-
f"Action handler plugin {trigger.action_subtype} "
|
118
|
-
f"for flavor {trigger.action_flavor} is not a valid action "
|
119
|
-
"handler plugin."
|
120
|
-
)
|
121
|
-
|
122
|
-
triggers.items[idx] = action_handler.get_trigger(
|
123
|
-
trigger, hydrate=hydrate
|
124
|
-
)
|
125
|
-
|
126
|
-
return triggers
|
127
|
-
|
128
83
|
return verify_permissions_and_list_entities(
|
129
84
|
filter_model=trigger_filter_model,
|
130
85
|
resource_type=ResourceType.TRIGGER,
|
131
|
-
list_method=
|
86
|
+
list_method=zen_store().list_triggers,
|
87
|
+
hydrate=hydrate,
|
132
88
|
)
|
133
89
|
|
134
90
|
|
@@ -152,31 +108,9 @@ def get_trigger(
|
|
152
108
|
|
153
109
|
Returns:
|
154
110
|
The requested trigger.
|
155
|
-
|
156
|
-
Raises:
|
157
|
-
ValueError: If the action flavor/subtype combination is not actually a webhook event source
|
158
111
|
"""
|
159
112
|
trigger = zen_store().get_trigger(trigger_id=trigger_id, hydrate=hydrate)
|
160
|
-
|
161
113
|
verify_permission_for_model(trigger, action=Action.READ)
|
162
|
-
|
163
|
-
action_handler = plugin_flavor_registry().get_plugin(
|
164
|
-
name=trigger.action_flavor,
|
165
|
-
_type=PluginType.ACTION,
|
166
|
-
subtype=trigger.action_subtype,
|
167
|
-
)
|
168
|
-
|
169
|
-
# Validate that the flavor and plugin_type correspond to an action
|
170
|
-
# handler implementation
|
171
|
-
if not isinstance(action_handler, BaseActionHandler):
|
172
|
-
raise ValueError(
|
173
|
-
f"Action handler plugin {trigger.action_subtype} "
|
174
|
-
f"for flavor {trigger.action_flavor} is not a valid action "
|
175
|
-
"handler plugin."
|
176
|
-
)
|
177
|
-
|
178
|
-
trigger = action_handler.get_trigger(trigger, hydrate=hydrate)
|
179
|
-
|
180
114
|
return dehydrate_response_model(trigger)
|
181
115
|
|
182
116
|
|
@@ -201,55 +135,35 @@ def create_trigger(
|
|
201
135
|
Raises:
|
202
136
|
ValueError: If the action flavor/subtype combination is not actually a webhook event source
|
203
137
|
"""
|
204
|
-
if trigger.
|
205
|
-
|
206
|
-
|
138
|
+
if trigger.event_source_id and trigger.event_filter:
|
139
|
+
event_source = zen_store().get_event_source(
|
140
|
+
event_source_id=trigger.event_source_id
|
207
141
|
)
|
208
|
-
verify_permission_for_model(service_account, action=Action.READ)
|
209
|
-
|
210
|
-
event_source = zen_store().get_event_source(
|
211
|
-
event_source_id=trigger.event_source_id
|
212
|
-
)
|
213
142
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
)
|
219
|
-
|
220
|
-
# Validate that the flavor and plugin_type correspond to an event source
|
221
|
-
# implementation
|
222
|
-
if not isinstance(event_source_handler, BaseEventSourceHandler):
|
223
|
-
raise ValueError(
|
224
|
-
f"Event source plugin {event_source.plugin_subtype} "
|
225
|
-
f"for flavor {event_source.flavor} is not a valid event source "
|
226
|
-
"handler implementation."
|
143
|
+
event_source_handler = plugin_flavor_registry().get_plugin(
|
144
|
+
name=event_source.flavor,
|
145
|
+
_type=PluginType.EVENT_SOURCE,
|
146
|
+
subtype=event_source.plugin_subtype,
|
227
147
|
)
|
228
148
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
subtype=trigger.action_subtype,
|
238
|
-
)
|
149
|
+
# Validate that the flavor and plugin_type correspond to an event source
|
150
|
+
# implementation
|
151
|
+
if not isinstance(event_source_handler, BaseEventSourceHandler):
|
152
|
+
raise ValueError(
|
153
|
+
f"Event source plugin {event_source.plugin_subtype} "
|
154
|
+
f"for flavor {event_source.flavor} is not a valid event source "
|
155
|
+
"handler implementation."
|
156
|
+
)
|
239
157
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
raise ValueError(
|
244
|
-
f"Action handler plugin {trigger.action_subtype} "
|
245
|
-
f"for flavor {trigger.action_flavor} is not a valid action "
|
246
|
-
"handler plugin."
|
158
|
+
# Validate the trigger event filter
|
159
|
+
event_source_handler.validate_event_filter_configuration(
|
160
|
+
trigger.event_filter
|
247
161
|
)
|
248
162
|
|
249
163
|
return verify_permissions_and_create_entity(
|
250
164
|
request_model=trigger,
|
251
165
|
resource_type=ResourceType.TRIGGER,
|
252
|
-
create_method=
|
166
|
+
create_method=zen_store().create_trigger,
|
253
167
|
)
|
254
168
|
|
255
169
|
|
@@ -278,13 +192,12 @@ def update_trigger(
|
|
278
192
|
"""
|
279
193
|
trigger = zen_store().get_trigger(trigger_id=trigger_id)
|
280
194
|
|
281
|
-
if trigger_update.service_account_id:
|
282
|
-
service_account = zen_store().get_service_account(
|
283
|
-
service_account_name_or_id=trigger_update.service_account_id
|
284
|
-
)
|
285
|
-
verify_permission_for_model(service_account, action=Action.READ)
|
286
|
-
|
287
195
|
if trigger_update.event_filter:
|
196
|
+
if not trigger.event_source:
|
197
|
+
raise ValueError(
|
198
|
+
"Trying to set event filter for trigger without event source."
|
199
|
+
)
|
200
|
+
|
288
201
|
event_source = zen_store().get_event_source(
|
289
202
|
event_source_id=trigger.event_source.id
|
290
203
|
)
|
@@ -306,29 +219,13 @@ def update_trigger(
|
|
306
219
|
|
307
220
|
# Validate the trigger event filter
|
308
221
|
event_source_handler.validate_event_filter_configuration(
|
309
|
-
|
222
|
+
trigger_update.event_filter
|
310
223
|
)
|
311
224
|
|
312
225
|
verify_permission_for_model(trigger, action=Action.UPDATE)
|
313
226
|
|
314
|
-
|
315
|
-
|
316
|
-
_type=PluginType.ACTION,
|
317
|
-
subtype=trigger.action_subtype,
|
318
|
-
)
|
319
|
-
|
320
|
-
# Validate that the flavor and plugin_type correspond to an action
|
321
|
-
# handler implementation
|
322
|
-
if not isinstance(action_handler, BaseActionHandler):
|
323
|
-
raise ValueError(
|
324
|
-
f"Action handler plugin {trigger.action_subtype} "
|
325
|
-
f"for flavor {trigger.action_flavor} is not a valid action "
|
326
|
-
"handler plugin."
|
327
|
-
)
|
328
|
-
|
329
|
-
updated_trigger = action_handler.update_trigger(
|
330
|
-
trigger=trigger,
|
331
|
-
trigger_update=trigger_update,
|
227
|
+
updated_trigger = zen_store().update_trigger(
|
228
|
+
trigger_id=trigger_id, trigger_update=trigger_update
|
332
229
|
)
|
333
230
|
|
334
231
|
return dehydrate_response_model(updated_trigger)
|
@@ -341,41 +238,16 @@ def update_trigger(
|
|
341
238
|
@handle_exceptions
|
342
239
|
def delete_trigger(
|
343
240
|
trigger_id: UUID,
|
344
|
-
force: bool = False,
|
345
241
|
_: AuthContext = Security(authorize),
|
346
242
|
) -> None:
|
347
243
|
"""Deletes a trigger.
|
348
244
|
|
349
245
|
Args:
|
350
246
|
trigger_id: Name of the trigger.
|
351
|
-
force: Flag deciding whether to force delete the trigger.
|
352
|
-
|
353
|
-
Raises:
|
354
|
-
ValueError: If the action flavor/subtype combination is not actually a webhook event source
|
355
247
|
"""
|
356
248
|
trigger = zen_store().get_trigger(trigger_id=trigger_id)
|
357
|
-
|
358
249
|
verify_permission_for_model(trigger, action=Action.DELETE)
|
359
|
-
|
360
|
-
action_handler = plugin_flavor_registry().get_plugin(
|
361
|
-
name=trigger.action_flavor,
|
362
|
-
_type=PluginType.ACTION,
|
363
|
-
subtype=trigger.action_subtype,
|
364
|
-
)
|
365
|
-
|
366
|
-
# Validate that the flavor and plugin_type correspond to an action
|
367
|
-
# handler implementation
|
368
|
-
if not isinstance(action_handler, BaseActionHandler):
|
369
|
-
raise ValueError(
|
370
|
-
f"Action handler plugin {trigger.action_subtype} "
|
371
|
-
f"for flavor {trigger.action_flavor} is not a valid action "
|
372
|
-
"handler plugin."
|
373
|
-
)
|
374
|
-
|
375
|
-
action_handler.delete_trigger(
|
376
|
-
trigger=trigger,
|
377
|
-
force=force,
|
378
|
-
)
|
250
|
+
zen_store().delete_trigger(trigger_id=trigger_id)
|
379
251
|
|
380
252
|
|
381
253
|
executions_router = APIRouter(
|
@@ -40,6 +40,7 @@ from zenml.constants import API, HEALTH
|
|
40
40
|
from zenml.enums import AuthScheme, SourceContextTypes
|
41
41
|
from zenml.zen_server.exceptions import error_detail
|
42
42
|
from zenml.zen_server.routers import (
|
43
|
+
actions_endpoints,
|
43
44
|
artifact_endpoint,
|
44
45
|
artifact_version_endpoints,
|
45
46
|
auth_endpoints,
|
@@ -262,6 +263,7 @@ async def dashboard(request: Request) -> Any:
|
|
262
263
|
return templates.TemplateResponse("index.html", {"request": request})
|
263
264
|
|
264
265
|
|
266
|
+
app.include_router(actions_endpoints.router)
|
265
267
|
app.include_router(artifact_endpoint.artifact_router)
|
266
268
|
app.include_router(artifact_version_endpoints.artifact_version_router)
|
267
269
|
app.include_router(auth_endpoints.router)
|
@@ -0,0 +1,228 @@
|
|
1
|
+
"""Separate actions and triggers [25155145c545].
|
2
|
+
|
3
|
+
Revision ID: 25155145c545
|
4
|
+
Revises: 0.58.2
|
5
|
+
Create Date: 2024-05-16 11:29:53.341275
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
from datetime import datetime
|
10
|
+
from uuid import uuid4
|
11
|
+
|
12
|
+
import sqlalchemy as sa
|
13
|
+
import sqlmodel
|
14
|
+
from alembic import op
|
15
|
+
|
16
|
+
# revision identifiers, used by Alembic.
|
17
|
+
revision = "25155145c545"
|
18
|
+
down_revision = "0.58.2"
|
19
|
+
branch_labels = None
|
20
|
+
depends_on = None
|
21
|
+
|
22
|
+
|
23
|
+
def migrate_actions() -> None:
|
24
|
+
"""Migrate actions from the trigger table."""
|
25
|
+
conn = op.get_bind()
|
26
|
+
meta = sa.MetaData()
|
27
|
+
meta.reflect(only=("trigger", "action"), bind=op.get_bind())
|
28
|
+
trigger_table = sa.Table("trigger", meta)
|
29
|
+
action_table = sa.Table("action", meta)
|
30
|
+
|
31
|
+
triggers = conn.execute(
|
32
|
+
sa.select(
|
33
|
+
trigger_table.c.id,
|
34
|
+
trigger_table.c.name,
|
35
|
+
trigger_table.c.user_id,
|
36
|
+
trigger_table.c.workspace_id,
|
37
|
+
trigger_table.c.service_account_id,
|
38
|
+
trigger_table.c.auth_window,
|
39
|
+
trigger_table.c.action,
|
40
|
+
trigger_table.c.action_subtype,
|
41
|
+
trigger_table.c.action_flavor,
|
42
|
+
)
|
43
|
+
).fetchall()
|
44
|
+
|
45
|
+
now = datetime.utcnow()
|
46
|
+
|
47
|
+
actions_to_insert = []
|
48
|
+
trigger_updates = {}
|
49
|
+
for trigger in triggers:
|
50
|
+
action_id = str(uuid4()).replace("-", "")
|
51
|
+
|
52
|
+
actions_to_insert.append(
|
53
|
+
{
|
54
|
+
"id": action_id,
|
55
|
+
"workspace_id": trigger.workspace_id,
|
56
|
+
"user_id": trigger.user_id,
|
57
|
+
"created": now,
|
58
|
+
"updated": now,
|
59
|
+
"name": f"{trigger.name}_action",
|
60
|
+
"description": f"Automatically migrated action for trigger {trigger.name}",
|
61
|
+
"service_account_id": trigger.service_account_id,
|
62
|
+
"auth_window": trigger.auth_window,
|
63
|
+
"configuration": trigger.action,
|
64
|
+
"flavor": trigger.action_flavor,
|
65
|
+
"plugin_subtype": trigger.action_subtype,
|
66
|
+
}
|
67
|
+
)
|
68
|
+
|
69
|
+
trigger_updates[trigger.id] = action_id
|
70
|
+
|
71
|
+
op.bulk_insert(action_table, actions_to_insert)
|
72
|
+
|
73
|
+
for trigger_id, action_id in trigger_updates.items():
|
74
|
+
query = (
|
75
|
+
sa.update(trigger_table)
|
76
|
+
.where(trigger_table.c.id.is_(trigger_id))
|
77
|
+
.values(action_id=action_id)
|
78
|
+
)
|
79
|
+
conn.execute(query)
|
80
|
+
|
81
|
+
|
82
|
+
def upgrade() -> None:
|
83
|
+
"""Upgrade database schema and/or data, creating a new revision."""
|
84
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
85
|
+
op.create_table(
|
86
|
+
"action",
|
87
|
+
sa.Column(
|
88
|
+
"workspace_id", sqlmodel.sql.sqltypes.GUID(), nullable=False
|
89
|
+
),
|
90
|
+
sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True),
|
91
|
+
sa.Column(
|
92
|
+
"service_account_id", sqlmodel.sql.sqltypes.GUID(), nullable=False
|
93
|
+
),
|
94
|
+
sa.Column("description", sa.TEXT(), nullable=True),
|
95
|
+
sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
|
96
|
+
sa.Column("created", sa.DateTime(), nullable=False),
|
97
|
+
sa.Column("updated", sa.DateTime(), nullable=False),
|
98
|
+
sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
99
|
+
sa.Column("auth_window", sa.Integer(), nullable=False),
|
100
|
+
sa.Column(
|
101
|
+
"flavor", sqlmodel.sql.sqltypes.AutoString(), nullable=False
|
102
|
+
),
|
103
|
+
sa.Column(
|
104
|
+
"plugin_subtype",
|
105
|
+
sqlmodel.sql.sqltypes.AutoString(),
|
106
|
+
nullable=False,
|
107
|
+
),
|
108
|
+
sa.Column("configuration", sa.LargeBinary(), nullable=False),
|
109
|
+
sa.ForeignKeyConstraint(
|
110
|
+
["service_account_id"],
|
111
|
+
["user.id"],
|
112
|
+
name="fk_action_service_account_id_user",
|
113
|
+
ondelete="CASCADE",
|
114
|
+
),
|
115
|
+
sa.ForeignKeyConstraint(
|
116
|
+
["user_id"],
|
117
|
+
["user.id"],
|
118
|
+
name="fk_action_user_id_user",
|
119
|
+
ondelete="SET NULL",
|
120
|
+
),
|
121
|
+
sa.ForeignKeyConstraint(
|
122
|
+
["workspace_id"],
|
123
|
+
["workspace.id"],
|
124
|
+
name="fk_action_workspace_id_workspace",
|
125
|
+
ondelete="CASCADE",
|
126
|
+
),
|
127
|
+
sa.PrimaryKeyConstraint("id"),
|
128
|
+
)
|
129
|
+
|
130
|
+
# Add the action_id column as nullable until we migrate the actions into
|
131
|
+
# a separate table
|
132
|
+
with op.batch_alter_table("trigger", schema=None) as batch_op:
|
133
|
+
batch_op.add_column(
|
134
|
+
sa.Column("action_id", sqlmodel.sql.sqltypes.GUID(), nullable=True)
|
135
|
+
)
|
136
|
+
|
137
|
+
migrate_actions()
|
138
|
+
|
139
|
+
with op.batch_alter_table("trigger", schema=None) as batch_op:
|
140
|
+
# Make the action_id column non-nullable now that we've inserted the
|
141
|
+
# actions and the value is set for each row
|
142
|
+
batch_op.alter_column(
|
143
|
+
"action_id",
|
144
|
+
existing_type=sqlmodel.sql.sqltypes.GUID(),
|
145
|
+
existing_nullable=True,
|
146
|
+
nullable=False,
|
147
|
+
)
|
148
|
+
|
149
|
+
batch_op.add_column(
|
150
|
+
sa.Column("schedule", sa.LargeBinary(), nullable=True)
|
151
|
+
)
|
152
|
+
batch_op.alter_column(
|
153
|
+
"event_source_id", existing_type=sa.CHAR(length=32), nullable=True
|
154
|
+
)
|
155
|
+
batch_op.drop_constraint(
|
156
|
+
"fk_trigger_event_source_id_event_source", type_="foreignkey"
|
157
|
+
)
|
158
|
+
batch_op.drop_constraint(
|
159
|
+
"fk_trigger_service_account_id_user", type_="foreignkey"
|
160
|
+
)
|
161
|
+
batch_op.create_foreign_key(
|
162
|
+
"fk_trigger_event_source_id_event_source",
|
163
|
+
"event_source",
|
164
|
+
["event_source_id"],
|
165
|
+
["id"],
|
166
|
+
ondelete="SET NULL",
|
167
|
+
)
|
168
|
+
batch_op.create_foreign_key(
|
169
|
+
"fk_trigger_action_id_action",
|
170
|
+
"action",
|
171
|
+
["action_id"],
|
172
|
+
["id"],
|
173
|
+
ondelete="CASCADE",
|
174
|
+
)
|
175
|
+
batch_op.drop_column("action_subtype")
|
176
|
+
batch_op.drop_column("action_flavor")
|
177
|
+
batch_op.drop_column("action")
|
178
|
+
batch_op.drop_column("auth_window")
|
179
|
+
batch_op.drop_column("service_account_id")
|
180
|
+
|
181
|
+
# ### end Alembic commands ###
|
182
|
+
|
183
|
+
|
184
|
+
def downgrade() -> None:
|
185
|
+
"""Downgrade database schema and/or data back to the previous revision."""
|
186
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
187
|
+
with op.batch_alter_table("trigger", schema=None) as batch_op:
|
188
|
+
batch_op.add_column(
|
189
|
+
sa.Column("service_account_id", sa.CHAR(length=32), nullable=False)
|
190
|
+
)
|
191
|
+
batch_op.add_column(
|
192
|
+
sa.Column("auth_window", sa.INTEGER(), nullable=False)
|
193
|
+
)
|
194
|
+
batch_op.add_column(sa.Column("action", sa.BLOB(), nullable=False))
|
195
|
+
batch_op.add_column(
|
196
|
+
sa.Column("action_flavor", sa.VARCHAR(), nullable=False)
|
197
|
+
)
|
198
|
+
batch_op.add_column(
|
199
|
+
sa.Column("action_subtype", sa.VARCHAR(), nullable=False)
|
200
|
+
)
|
201
|
+
batch_op.drop_constraint(
|
202
|
+
"fk_trigger_action_id_action", type_="foreignkey"
|
203
|
+
)
|
204
|
+
batch_op.drop_constraint(
|
205
|
+
"fk_trigger_event_source_id_event_source", type_="foreignkey"
|
206
|
+
)
|
207
|
+
batch_op.create_foreign_key(
|
208
|
+
"fk_trigger_service_account_id_user",
|
209
|
+
"user",
|
210
|
+
["service_account_id"],
|
211
|
+
["id"],
|
212
|
+
ondelete="CASCADE",
|
213
|
+
)
|
214
|
+
batch_op.create_foreign_key(
|
215
|
+
"fk_trigger_event_source_id_event_source",
|
216
|
+
"event_source",
|
217
|
+
["event_source_id"],
|
218
|
+
["id"],
|
219
|
+
ondelete="CASCADE",
|
220
|
+
)
|
221
|
+
batch_op.alter_column(
|
222
|
+
"event_source_id", existing_type=sa.CHAR(length=32), nullable=False
|
223
|
+
)
|
224
|
+
batch_op.drop_column("schedule")
|
225
|
+
batch_op.drop_column("action_id")
|
226
|
+
|
227
|
+
op.drop_table("action")
|
228
|
+
# ### end Alembic commands ###
|
@@ -47,6 +47,7 @@ from zenml.config.global_config import GlobalConfiguration
|
|
47
47
|
from zenml.config.pipeline_run_configuration import PipelineRunConfiguration
|
48
48
|
from zenml.config.store_config import StoreConfiguration
|
49
49
|
from zenml.constants import (
|
50
|
+
ACTIONS,
|
50
51
|
API,
|
51
52
|
API_KEY_ROTATE,
|
52
53
|
API_KEYS,
|
@@ -108,6 +109,10 @@ from zenml.exceptions import AuthorizationException, MethodNotAllowedError
|
|
108
109
|
from zenml.io import fileio
|
109
110
|
from zenml.logger import get_logger
|
110
111
|
from zenml.models import (
|
112
|
+
ActionFilter,
|
113
|
+
ActionRequest,
|
114
|
+
ActionResponse,
|
115
|
+
ActionUpdate,
|
111
116
|
APIKeyFilter,
|
112
117
|
APIKeyRequest,
|
113
118
|
APIKeyResponse,
|
@@ -480,6 +485,100 @@ class RestZenStore(BaseZenStore):
|
|
480
485
|
response_body = self.put(SERVER_SETTINGS, body=settings_update)
|
481
486
|
return ServerSettingsResponse.model_validate(response_body)
|
482
487
|
|
488
|
+
# -------------------- Actions --------------------
|
489
|
+
|
490
|
+
def create_action(self, action: ActionRequest) -> ActionResponse:
|
491
|
+
"""Create an action.
|
492
|
+
|
493
|
+
Args:
|
494
|
+
action: The action to create.
|
495
|
+
|
496
|
+
Returns:
|
497
|
+
The created action.
|
498
|
+
"""
|
499
|
+
return self._create_resource(
|
500
|
+
resource=action,
|
501
|
+
route=ACTIONS,
|
502
|
+
response_model=ActionResponse,
|
503
|
+
)
|
504
|
+
|
505
|
+
def get_action(
|
506
|
+
self,
|
507
|
+
action_id: UUID,
|
508
|
+
hydrate: bool = True,
|
509
|
+
) -> ActionResponse:
|
510
|
+
"""Get an action by ID.
|
511
|
+
|
512
|
+
Args:
|
513
|
+
action_id: The ID of the action to get.
|
514
|
+
hydrate: Flag deciding whether to hydrate the output model(s)
|
515
|
+
by including metadata fields in the response.
|
516
|
+
|
517
|
+
Returns:
|
518
|
+
The action.
|
519
|
+
"""
|
520
|
+
return self._get_resource(
|
521
|
+
resource_id=action_id,
|
522
|
+
route=ACTIONS,
|
523
|
+
response_model=ActionResponse,
|
524
|
+
params={"hydrate": hydrate},
|
525
|
+
)
|
526
|
+
|
527
|
+
def list_actions(
|
528
|
+
self,
|
529
|
+
action_filter_model: ActionFilter,
|
530
|
+
hydrate: bool = False,
|
531
|
+
) -> Page[ActionResponse]:
|
532
|
+
"""List all actions matching the given filter criteria.
|
533
|
+
|
534
|
+
Args:
|
535
|
+
action_filter_model: All filter parameters including pagination
|
536
|
+
params.
|
537
|
+
hydrate: Flag deciding whether to hydrate the output model(s)
|
538
|
+
by including metadata fields in the response.
|
539
|
+
|
540
|
+
Returns:
|
541
|
+
A list of all actions matching the filter criteria.
|
542
|
+
"""
|
543
|
+
return self._list_paginated_resources(
|
544
|
+
route=ACTIONS,
|
545
|
+
response_model=ActionResponse,
|
546
|
+
filter_model=action_filter_model,
|
547
|
+
params={"hydrate": hydrate},
|
548
|
+
)
|
549
|
+
|
550
|
+
def update_action(
|
551
|
+
self,
|
552
|
+
action_id: UUID,
|
553
|
+
action_update: ActionUpdate,
|
554
|
+
) -> ActionResponse:
|
555
|
+
"""Update an existing action.
|
556
|
+
|
557
|
+
Args:
|
558
|
+
action_id: The ID of the action to update.
|
559
|
+
action_update: The update to be applied to the action.
|
560
|
+
|
561
|
+
Returns:
|
562
|
+
The updated action.
|
563
|
+
"""
|
564
|
+
return self._update_resource(
|
565
|
+
resource_id=action_id,
|
566
|
+
resource_update=action_update,
|
567
|
+
route=ACTIONS,
|
568
|
+
response_model=ActionResponse,
|
569
|
+
)
|
570
|
+
|
571
|
+
def delete_action(self, action_id: UUID) -> None:
|
572
|
+
"""Delete an action.
|
573
|
+
|
574
|
+
Args:
|
575
|
+
action_id: The ID of the action to delete.
|
576
|
+
"""
|
577
|
+
self._delete_resource(
|
578
|
+
resource_id=action_id,
|
579
|
+
route=ACTIONS,
|
580
|
+
)
|
581
|
+
|
483
582
|
# ----------------------------- API Keys -----------------------------
|
484
583
|
|
485
584
|
def create_api_key(
|
@@ -1434,14 +1533,14 @@ class RestZenStore(BaseZenStore):
|
|
1434
1533
|
run_configuration = run_configuration or PipelineRunConfiguration()
|
1435
1534
|
try:
|
1436
1535
|
response_body = self.post(
|
1437
|
-
f"{PIPELINE_BUILDS}/{build_id}/
|
1536
|
+
f"{PIPELINE_BUILDS}/{build_id}/runs", body=run_configuration
|
1438
1537
|
)
|
1439
1538
|
except MethodNotAllowedError as e:
|
1440
1539
|
raise RuntimeError(
|
1441
1540
|
"Running a build is not supported for this server."
|
1442
1541
|
) from e
|
1443
1542
|
|
1444
|
-
return PipelineRunResponse.
|
1543
|
+
return PipelineRunResponse.model_validate(response_body)
|
1445
1544
|
|
1446
1545
|
# -------------------------- Pipeline Deployments --------------------------
|
1447
1546
|
|
@@ -1538,7 +1637,7 @@ class RestZenStore(BaseZenStore):
|
|
1538
1637
|
|
1539
1638
|
try:
|
1540
1639
|
response_body = self.post(
|
1541
|
-
f"{PIPELINE_DEPLOYMENTS}/{deployment_id}/
|
1640
|
+
f"{PIPELINE_DEPLOYMENTS}/{deployment_id}/runs",
|
1542
1641
|
body=run_configuration,
|
1543
1642
|
)
|
1544
1643
|
except MethodNotAllowedError as e:
|
@@ -1546,7 +1645,7 @@ class RestZenStore(BaseZenStore):
|
|
1546
1645
|
"Running a deployment is not supported for this server."
|
1547
1646
|
) from e
|
1548
1647
|
|
1549
|
-
return PipelineRunResponse.
|
1648
|
+
return PipelineRunResponse.model_validate(response_body)
|
1550
1649
|
|
1551
1650
|
# -------------------- Event Sources --------------------
|
1552
1651
|
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""SQL Model Implementations."""
|
15
15
|
|
16
|
+
from zenml.zen_stores.schemas.action_schemas import ActionSchema
|
16
17
|
from zenml.zen_stores.schemas.api_key_schemas import APIKeySchema
|
17
18
|
from zenml.zen_stores.schemas.artifact_schemas import (
|
18
19
|
ArtifactSchema,
|
@@ -71,6 +72,7 @@ from zenml.zen_stores.schemas.model_schemas import (
|
|
71
72
|
from zenml.zen_stores.schemas.server_settings_schemas import ServerSettingsSchema
|
72
73
|
|
73
74
|
__all__ = [
|
75
|
+
"ActionSchema",
|
74
76
|
"APIKeySchema",
|
75
77
|
"ArtifactSchema",
|
76
78
|
"ArtifactVersionSchema",
|