zenml-nightly 0.75.0.dev20250312__py3-none-any.whl → 0.75.0.dev20250314__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/__init__.py +2 -0
- zenml/analytics/context.py +7 -0
- zenml/analytics/enums.py +2 -2
- zenml/artifacts/utils.py +2 -4
- zenml/cli/__init__.py +8 -9
- zenml/cli/base.py +2 -2
- zenml/cli/code_repository.py +1 -1
- zenml/cli/login.py +6 -0
- zenml/cli/model.py +7 -15
- zenml/cli/pipeline.py +3 -3
- zenml/cli/project.py +172 -0
- zenml/cli/secret.py +47 -44
- zenml/cli/service_accounts.py +0 -1
- zenml/cli/service_connectors.py +15 -17
- zenml/cli/stack.py +0 -3
- zenml/cli/stack_components.py +2 -2
- zenml/cli/tag.py +3 -5
- zenml/cli/utils.py +25 -23
- zenml/client.py +749 -475
- zenml/config/global_config.py +48 -37
- zenml/config/pipeline_configurations.py +3 -2
- zenml/config/pipeline_run_configuration.py +2 -1
- zenml/config/secret_reference_mixin.py +1 -1
- zenml/constants.py +6 -6
- zenml/enums.py +0 -7
- zenml/event_hub/event_hub.py +3 -1
- zenml/exceptions.py +0 -24
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +5 -3
- zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +1 -4
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +7 -6
- zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +1 -4
- zenml/integrations/mlflow/steps/mlflow_registry.py +3 -3
- zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -1
- 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 +5 -3
- zenml/model/model.py +10 -10
- zenml/model_registries/base_model_registry.py +1 -1
- zenml/models/__init__.py +45 -28
- zenml/models/v2/base/base.py +0 -5
- zenml/models/v2/base/filter.py +2 -2
- zenml/models/v2/base/scoped.py +135 -156
- zenml/models/v2/core/action.py +12 -12
- zenml/models/v2/core/api_key.py +1 -1
- zenml/models/v2/core/artifact.py +31 -18
- zenml/models/v2/core/artifact_version.py +57 -40
- zenml/models/v2/core/code_repository.py +12 -12
- zenml/models/v2/core/component.py +22 -33
- zenml/models/v2/core/device.py +3 -2
- zenml/models/v2/core/event_source.py +14 -14
- zenml/models/v2/core/flavor.py +19 -47
- zenml/models/v2/core/logs.py +1 -2
- zenml/models/v2/core/model.py +23 -20
- zenml/models/v2/core/model_version.py +51 -42
- zenml/models/v2/core/pipeline.py +16 -16
- 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 +21 -29
- zenml/models/v2/core/project.py +203 -0
- zenml/models/v2/core/run_metadata.py +2 -2
- zenml/models/v2/core/run_template.py +16 -17
- zenml/models/v2/core/schedule.py +12 -21
- zenml/models/v2/core/secret.py +94 -128
- zenml/models/v2/core/server_settings.py +2 -2
- zenml/models/v2/core/service.py +57 -26
- zenml/models/v2/core/service_connector.py +14 -16
- zenml/models/v2/core/stack.py +24 -26
- zenml/models/v2/core/step_run.py +16 -28
- zenml/models/v2/core/tag.py +41 -15
- zenml/models/v2/core/trigger.py +13 -13
- zenml/models/v2/core/trigger_execution.py +2 -2
- zenml/models/v2/core/user.py +2 -2
- zenml/models/v2/misc/statistics.py +45 -0
- zenml/models/v2/misc/tag.py +27 -0
- zenml/orchestrators/cache_utils.py +7 -7
- zenml/orchestrators/input_utils.py +1 -0
- zenml/orchestrators/step_launcher.py +1 -2
- zenml/orchestrators/step_run_utils.py +2 -4
- zenml/orchestrators/step_runner.py +10 -1
- zenml/orchestrators/utils.py +4 -4
- zenml/pipelines/build_utils.py +2 -4
- zenml/pipelines/pipeline_decorator.py +3 -2
- zenml/pipelines/pipeline_definition.py +8 -9
- zenml/pipelines/run_utils.py +4 -4
- zenml/service_connectors/service_connector.py +0 -10
- zenml/service_connectors/service_connector_utils.py +0 -2
- zenml/stack/authentication_mixin.py +1 -1
- zenml/stack/flavor.py +3 -14
- zenml/stack/stack.py +0 -1
- zenml/stack/stack_component.py +1 -5
- zenml/steps/base_step.py +10 -2
- zenml/steps/step_context.py +19 -0
- zenml/utils/string_utils.py +1 -1
- zenml/utils/tag_utils.py +642 -0
- zenml/zen_server/cloud_utils.py +21 -0
- zenml/zen_server/exceptions.py +0 -6
- zenml/zen_server/rbac/endpoint_utils.py +134 -46
- zenml/zen_server/rbac/models.py +65 -3
- zenml/zen_server/rbac/rbac_interface.py +9 -0
- zenml/zen_server/rbac/rbac_sql_zen_store.py +15 -7
- zenml/zen_server/rbac/utils.py +155 -30
- zenml/zen_server/rbac/zenml_cloud_rbac.py +39 -11
- zenml/zen_server/routers/actions_endpoints.py +3 -5
- zenml/zen_server/routers/artifact_endpoint.py +0 -5
- zenml/zen_server/routers/artifact_version_endpoints.py +15 -9
- zenml/zen_server/routers/auth_endpoints.py +22 -7
- zenml/zen_server/routers/code_repositories_endpoints.py +54 -3
- zenml/zen_server/routers/devices_endpoints.py +0 -4
- zenml/zen_server/routers/event_source_endpoints.py +0 -5
- zenml/zen_server/routers/flavors_endpoints.py +0 -5
- zenml/zen_server/routers/logs_endpoints.py +0 -1
- zenml/zen_server/routers/model_versions_endpoints.py +100 -23
- zenml/zen_server/routers/models_endpoints.py +50 -69
- zenml/zen_server/routers/pipeline_builds_endpoints.py +55 -3
- zenml/zen_server/routers/pipeline_deployments_endpoints.py +56 -4
- zenml/zen_server/routers/pipelines_endpoints.py +70 -3
- zenml/zen_server/routers/plugin_endpoints.py +0 -1
- zenml/zen_server/routers/projects_endpoints.py +283 -0
- zenml/zen_server/routers/run_metadata_endpoints.py +97 -0
- zenml/zen_server/routers/run_templates_endpoints.py +64 -3
- zenml/zen_server/routers/runs_endpoints.py +58 -8
- zenml/zen_server/routers/schedule_endpoints.py +67 -6
- zenml/zen_server/routers/secrets_endpoints.py +38 -4
- zenml/zen_server/routers/server_endpoints.py +53 -1
- zenml/zen_server/routers/service_accounts_endpoints.py +14 -15
- zenml/zen_server/routers/service_connectors_endpoints.py +94 -14
- zenml/zen_server/routers/service_endpoints.py +18 -7
- zenml/zen_server/routers/stack_components_endpoints.py +66 -7
- zenml/zen_server/routers/stacks_endpoints.py +95 -6
- zenml/zen_server/routers/steps_endpoints.py +17 -11
- zenml/zen_server/routers/tag_resource_endpoints.py +115 -0
- zenml/zen_server/routers/tags_endpoints.py +6 -17
- zenml/zen_server/routers/triggers_endpoints.py +5 -8
- zenml/zen_server/routers/users_endpoints.py +9 -12
- zenml/zen_server/template_execution/utils.py +8 -7
- zenml/zen_server/utils.py +21 -0
- zenml/zen_server/zen_server_api.py +7 -2
- zenml/zen_stores/base_zen_store.py +50 -69
- zenml/zen_stores/migrations/versions/12eff0206201_rename_workspace_to_project.py +768 -0
- zenml/zen_stores/migrations/versions/1cb6477f72d6_move_artifact_save_type.py +20 -10
- zenml/zen_stores/migrations/versions/1f9d1cd00b90_add_unique_name_constraints.py +231 -0
- zenml/zen_stores/migrations/versions/288f4fb6e112_make_tags_user_scoped.py +74 -0
- zenml/zen_stores/migrations/versions/2e695a26fe7a_add_user_default_workspace.py +45 -0
- zenml/zen_stores/migrations/versions/3b1776345020_remove_workspace_from_globals.py +81 -0
- zenml/zen_stores/migrations/versions/41b28cae31ce_make_artifacts_workspace_scoped.py +136 -0
- zenml/zen_stores/migrations/versions/9e7bf0970266_adding_exclusive_attribute_to_tags.py +47 -0
- zenml/zen_stores/migrations/versions/b557b2871693_update_step_run_input_types.py +8 -4
- zenml/zen_stores/migrations/versions/cbc6acd71f92_add_workspace_display_name.py +58 -0
- zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +12 -6
- zenml/zen_stores/migrations/versions/f1d723fd723b_add_secret_private_attr.py +61 -0
- zenml/zen_stores/migrations/versions/f76a368a25a5_add_stack_description.py +35 -0
- zenml/zen_stores/rest_zen_store.py +223 -230
- zenml/zen_stores/schemas/__init__.py +2 -2
- zenml/zen_stores/schemas/action_schemas.py +15 -8
- zenml/zen_stores/schemas/api_key_schemas.py +8 -1
- zenml/zen_stores/schemas/artifact_schemas.py +35 -10
- zenml/zen_stores/schemas/code_repository_schemas.py +22 -17
- zenml/zen_stores/schemas/component_schemas.py +9 -14
- zenml/zen_stores/schemas/event_source_schemas.py +15 -8
- zenml/zen_stores/schemas/flavor_schemas.py +14 -20
- zenml/zen_stores/schemas/model_schemas.py +18 -17
- zenml/zen_stores/schemas/pipeline_build_schemas.py +7 -7
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +10 -8
- zenml/zen_stores/schemas/pipeline_run_schemas.py +9 -12
- zenml/zen_stores/schemas/pipeline_schemas.py +9 -9
- zenml/zen_stores/schemas/{workspace_schemas.py → project_schemas.py} +53 -65
- zenml/zen_stores/schemas/run_metadata_schemas.py +5 -5
- zenml/zen_stores/schemas/run_template_schemas.py +17 -13
- zenml/zen_stores/schemas/schedule_schema.py +16 -21
- zenml/zen_stores/schemas/secret_schemas.py +15 -25
- zenml/zen_stores/schemas/service_connector_schemas.py +8 -17
- zenml/zen_stores/schemas/service_schemas.py +7 -8
- zenml/zen_stores/schemas/stack_schemas.py +12 -15
- zenml/zen_stores/schemas/step_run_schemas.py +14 -15
- zenml/zen_stores/schemas/tag_schemas.py +30 -2
- zenml/zen_stores/schemas/trigger_schemas.py +15 -8
- zenml/zen_stores/schemas/user_schemas.py +12 -2
- zenml/zen_stores/schemas/utils.py +16 -0
- zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +0 -3
- zenml/zen_stores/sql_zen_store.py +2984 -2369
- zenml/zen_stores/template_utils.py +1 -1
- zenml/zen_stores/zen_store_interface.py +136 -126
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/METADATA +1 -1
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/RECORD +188 -173
- zenml/cli/workspace.py +0 -86
- zenml/models/v2/core/workspace.py +0 -131
- zenml/zen_server/routers/workspaces_endpoints.py +0 -1469
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,283 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2022. 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
|
+
"""Endpoint definitions for projects."""
|
15
|
+
|
16
|
+
from typing import Union
|
17
|
+
from uuid import UUID
|
18
|
+
|
19
|
+
from fastapi import APIRouter, Depends, Security
|
20
|
+
|
21
|
+
from zenml.constants import (
|
22
|
+
API,
|
23
|
+
PROJECTS,
|
24
|
+
STATISTICS,
|
25
|
+
VERSION_1,
|
26
|
+
WORKSPACES,
|
27
|
+
)
|
28
|
+
from zenml.models import (
|
29
|
+
Page,
|
30
|
+
PipelineFilter,
|
31
|
+
PipelineRunFilter,
|
32
|
+
ProjectFilter,
|
33
|
+
ProjectRequest,
|
34
|
+
ProjectResponse,
|
35
|
+
ProjectStatistics,
|
36
|
+
ProjectUpdate,
|
37
|
+
)
|
38
|
+
from zenml.zen_server.auth import AuthContext, authorize
|
39
|
+
from zenml.zen_server.exceptions import error_response
|
40
|
+
from zenml.zen_server.rbac.endpoint_utils import (
|
41
|
+
verify_permissions_and_create_entity,
|
42
|
+
verify_permissions_and_delete_entity,
|
43
|
+
verify_permissions_and_get_entity,
|
44
|
+
verify_permissions_and_list_entities,
|
45
|
+
verify_permissions_and_update_entity,
|
46
|
+
)
|
47
|
+
from zenml.zen_server.rbac.models import ResourceType
|
48
|
+
from zenml.zen_server.rbac.utils import (
|
49
|
+
get_allowed_resource_ids,
|
50
|
+
)
|
51
|
+
from zenml.zen_server.utils import (
|
52
|
+
handle_exceptions,
|
53
|
+
make_dependable,
|
54
|
+
zen_store,
|
55
|
+
)
|
56
|
+
|
57
|
+
workspace_router = APIRouter(
|
58
|
+
prefix=API + VERSION_1 + WORKSPACES,
|
59
|
+
tags=["workspaces"],
|
60
|
+
responses={401: error_response},
|
61
|
+
)
|
62
|
+
|
63
|
+
router = APIRouter(
|
64
|
+
prefix=API + VERSION_1 + PROJECTS,
|
65
|
+
tags=["projects"],
|
66
|
+
responses={401: error_response},
|
67
|
+
)
|
68
|
+
|
69
|
+
|
70
|
+
# TODO: kept for backwards compatibility only; to be removed after the migration
|
71
|
+
@workspace_router.get(
|
72
|
+
"",
|
73
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
74
|
+
deprecated=True,
|
75
|
+
)
|
76
|
+
@router.get(
|
77
|
+
"",
|
78
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
79
|
+
)
|
80
|
+
@handle_exceptions
|
81
|
+
def list_projects(
|
82
|
+
project_filter_model: ProjectFilter = Depends(
|
83
|
+
make_dependable(ProjectFilter)
|
84
|
+
),
|
85
|
+
hydrate: bool = False,
|
86
|
+
_: AuthContext = Security(authorize),
|
87
|
+
) -> Page[ProjectResponse]:
|
88
|
+
"""Lists all projects in the organization.
|
89
|
+
|
90
|
+
Args:
|
91
|
+
project_filter_model: Filter model used for pagination, sorting,
|
92
|
+
filtering,
|
93
|
+
hydrate: Flag deciding whether to hydrate the output model(s)
|
94
|
+
by including metadata fields in the response.
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
A list of projects.
|
98
|
+
"""
|
99
|
+
return verify_permissions_and_list_entities(
|
100
|
+
filter_model=project_filter_model,
|
101
|
+
resource_type=ResourceType.PROJECT,
|
102
|
+
list_method=zen_store().list_projects,
|
103
|
+
hydrate=hydrate,
|
104
|
+
)
|
105
|
+
|
106
|
+
|
107
|
+
# TODO: kept for backwards compatibility only; to be removed after the migration
|
108
|
+
@workspace_router.post(
|
109
|
+
"",
|
110
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
111
|
+
deprecated=True,
|
112
|
+
)
|
113
|
+
@router.post(
|
114
|
+
"",
|
115
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
116
|
+
)
|
117
|
+
@handle_exceptions
|
118
|
+
def create_project(
|
119
|
+
project_request: ProjectRequest,
|
120
|
+
_: AuthContext = Security(authorize),
|
121
|
+
) -> ProjectResponse:
|
122
|
+
"""Creates a project based on the requestBody.
|
123
|
+
|
124
|
+
# noqa: DAR401
|
125
|
+
|
126
|
+
Args:
|
127
|
+
project_request: Project to create.
|
128
|
+
|
129
|
+
Returns:
|
130
|
+
The created project.
|
131
|
+
"""
|
132
|
+
return verify_permissions_and_create_entity(
|
133
|
+
request_model=project_request,
|
134
|
+
create_method=zen_store().create_project,
|
135
|
+
)
|
136
|
+
|
137
|
+
|
138
|
+
# TODO: kept for backwards compatibility only; to be removed after the migration
|
139
|
+
@workspace_router.get(
|
140
|
+
"/{project_name_or_id}",
|
141
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
142
|
+
deprecated=True,
|
143
|
+
)
|
144
|
+
@router.get(
|
145
|
+
"/{project_name_or_id}",
|
146
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
147
|
+
)
|
148
|
+
@handle_exceptions
|
149
|
+
def get_project(
|
150
|
+
project_name_or_id: Union[str, UUID],
|
151
|
+
hydrate: bool = True,
|
152
|
+
_: AuthContext = Security(authorize),
|
153
|
+
) -> ProjectResponse:
|
154
|
+
"""Get a project for given name.
|
155
|
+
|
156
|
+
# noqa: DAR401
|
157
|
+
|
158
|
+
Args:
|
159
|
+
project_name_or_id: Name or ID of the project.
|
160
|
+
hydrate: Flag deciding whether to hydrate the output model(s)
|
161
|
+
by including metadata fields in the response.
|
162
|
+
|
163
|
+
Returns:
|
164
|
+
The requested project.
|
165
|
+
"""
|
166
|
+
return verify_permissions_and_get_entity(
|
167
|
+
id=project_name_or_id,
|
168
|
+
get_method=zen_store().get_project,
|
169
|
+
hydrate=hydrate,
|
170
|
+
)
|
171
|
+
|
172
|
+
|
173
|
+
# TODO: kept for backwards compatibility only; to be removed after the migration
|
174
|
+
@workspace_router.put(
|
175
|
+
"/{project_name_or_id}",
|
176
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
177
|
+
deprecated=True,
|
178
|
+
)
|
179
|
+
@router.put(
|
180
|
+
"/{project_name_or_id}",
|
181
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
182
|
+
)
|
183
|
+
@handle_exceptions
|
184
|
+
def update_project(
|
185
|
+
project_name_or_id: UUID,
|
186
|
+
project_update: ProjectUpdate,
|
187
|
+
_: AuthContext = Security(authorize),
|
188
|
+
) -> ProjectResponse:
|
189
|
+
"""Get a project for given name.
|
190
|
+
|
191
|
+
# noqa: DAR401
|
192
|
+
|
193
|
+
Args:
|
194
|
+
project_name_or_id: Name or ID of the project to update.
|
195
|
+
project_update: the project to use to update
|
196
|
+
|
197
|
+
Returns:
|
198
|
+
The updated project.
|
199
|
+
"""
|
200
|
+
return verify_permissions_and_update_entity(
|
201
|
+
id=project_name_or_id,
|
202
|
+
update_model=project_update,
|
203
|
+
get_method=zen_store().get_project,
|
204
|
+
update_method=zen_store().update_project,
|
205
|
+
)
|
206
|
+
|
207
|
+
|
208
|
+
# TODO: kept for backwards compatibility only; to be removed after the migration
|
209
|
+
@workspace_router.delete(
|
210
|
+
"/{project_name_or_id}",
|
211
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
212
|
+
deprecated=True,
|
213
|
+
)
|
214
|
+
@router.delete(
|
215
|
+
"/{project_name_or_id}",
|
216
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
217
|
+
)
|
218
|
+
@handle_exceptions
|
219
|
+
def delete_project(
|
220
|
+
project_name_or_id: Union[str, UUID],
|
221
|
+
_: AuthContext = Security(authorize),
|
222
|
+
) -> None:
|
223
|
+
"""Deletes a project.
|
224
|
+
|
225
|
+
Args:
|
226
|
+
project_name_or_id: Name or ID of the project.
|
227
|
+
"""
|
228
|
+
verify_permissions_and_delete_entity(
|
229
|
+
id=project_name_or_id,
|
230
|
+
get_method=zen_store().get_project,
|
231
|
+
delete_method=zen_store().delete_project,
|
232
|
+
)
|
233
|
+
|
234
|
+
|
235
|
+
# TODO: kept for backwards compatibility only; to be removed after the migration
|
236
|
+
@workspace_router.get(
|
237
|
+
"/{project_name_or_id}" + STATISTICS,
|
238
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
239
|
+
deprecated=True,
|
240
|
+
)
|
241
|
+
@router.get(
|
242
|
+
"/{project_name_or_id}" + STATISTICS,
|
243
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
244
|
+
)
|
245
|
+
@handle_exceptions
|
246
|
+
def get_project_statistics(
|
247
|
+
project_name_or_id: Union[str, UUID],
|
248
|
+
auth_context: AuthContext = Security(authorize),
|
249
|
+
) -> ProjectStatistics:
|
250
|
+
"""Gets statistics of a project.
|
251
|
+
|
252
|
+
# noqa: DAR401
|
253
|
+
|
254
|
+
Args:
|
255
|
+
project_name_or_id: Name or ID of the project to get statistics for.
|
256
|
+
auth_context: Authentication context.
|
257
|
+
|
258
|
+
Returns:
|
259
|
+
Project statistics.
|
260
|
+
"""
|
261
|
+
project = verify_permissions_and_get_entity(
|
262
|
+
id=project_name_or_id,
|
263
|
+
get_method=zen_store().get_project,
|
264
|
+
)
|
265
|
+
|
266
|
+
user_id = auth_context.user.id
|
267
|
+
|
268
|
+
run_filter = PipelineRunFilter(project=project.id)
|
269
|
+
run_filter.configure_rbac(
|
270
|
+
authenticated_user_id=user_id,
|
271
|
+
id=get_allowed_resource_ids(resource_type=ResourceType.PIPELINE_RUN),
|
272
|
+
)
|
273
|
+
|
274
|
+
pipeline_filter = PipelineFilter(project=project.id)
|
275
|
+
pipeline_filter.configure_rbac(
|
276
|
+
authenticated_user_id=user_id,
|
277
|
+
id=get_allowed_resource_ids(resource_type=ResourceType.PIPELINE),
|
278
|
+
)
|
279
|
+
|
280
|
+
return ProjectStatistics(
|
281
|
+
pipelines=zen_store().count_pipelines(filter_model=pipeline_filter),
|
282
|
+
runs=zen_store().count_runs(filter_model=run_filter),
|
283
|
+
)
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2025. 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
|
+
"""Endpoint definitions for run metadata."""
|
15
|
+
|
16
|
+
from typing import Any, List, Optional, Union
|
17
|
+
from uuid import UUID
|
18
|
+
|
19
|
+
from fastapi import APIRouter, Security
|
20
|
+
|
21
|
+
from zenml.constants import API, RUN_METADATA, VERSION_1
|
22
|
+
from zenml.enums import MetadataResourceTypes
|
23
|
+
from zenml.models import RunMetadataRequest
|
24
|
+
from zenml.zen_server.auth import AuthContext, authorize
|
25
|
+
from zenml.zen_server.exceptions import error_response
|
26
|
+
from zenml.zen_server.rbac.models import Action
|
27
|
+
from zenml.zen_server.rbac.utils import (
|
28
|
+
batch_verify_permissions_for_models,
|
29
|
+
verify_permission_for_model,
|
30
|
+
)
|
31
|
+
from zenml.zen_server.routers.projects_endpoints import workspace_router
|
32
|
+
from zenml.zen_server.utils import handle_exceptions, zen_store
|
33
|
+
|
34
|
+
router = APIRouter(
|
35
|
+
prefix=API + VERSION_1 + RUN_METADATA,
|
36
|
+
tags=["run_metadata"],
|
37
|
+
responses={401: error_response, 403: error_response},
|
38
|
+
)
|
39
|
+
|
40
|
+
|
41
|
+
@router.post(
|
42
|
+
"",
|
43
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
44
|
+
)
|
45
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
46
|
+
# and can be removed after the migration
|
47
|
+
@workspace_router.post(
|
48
|
+
"/{project_name_or_id}" + RUN_METADATA,
|
49
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
50
|
+
deprecated=True,
|
51
|
+
tags=["run_metadata"],
|
52
|
+
)
|
53
|
+
@handle_exceptions
|
54
|
+
def create_run_metadata(
|
55
|
+
run_metadata: RunMetadataRequest,
|
56
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
57
|
+
auth_context: AuthContext = Security(authorize),
|
58
|
+
) -> None:
|
59
|
+
"""Creates run metadata.
|
60
|
+
|
61
|
+
Args:
|
62
|
+
run_metadata: The run metadata to create.
|
63
|
+
project_name_or_id: Optional name or ID of the project.
|
64
|
+
auth_context: Authentication context.
|
65
|
+
|
66
|
+
Raises:
|
67
|
+
RuntimeError: If the resource type is not supported.
|
68
|
+
"""
|
69
|
+
if project_name_or_id:
|
70
|
+
project = zen_store().get_project(project_name_or_id)
|
71
|
+
run_metadata.project = project.id
|
72
|
+
|
73
|
+
run_metadata.user = auth_context.user.id
|
74
|
+
|
75
|
+
verify_models: List[Any] = []
|
76
|
+
for resource in run_metadata.resources:
|
77
|
+
if resource.type == MetadataResourceTypes.PIPELINE_RUN:
|
78
|
+
verify_models.append(zen_store().get_run(resource.id))
|
79
|
+
elif resource.type == MetadataResourceTypes.STEP_RUN:
|
80
|
+
verify_models.append(zen_store().get_run_step(resource.id))
|
81
|
+
elif resource.type == MetadataResourceTypes.ARTIFACT_VERSION:
|
82
|
+
verify_models.append(zen_store().get_artifact_version(resource.id))
|
83
|
+
elif resource.type == MetadataResourceTypes.MODEL_VERSION:
|
84
|
+
verify_models.append(zen_store().get_model_version(resource.id))
|
85
|
+
elif resource.type == MetadataResourceTypes.SCHEDULE:
|
86
|
+
verify_models.append(zen_store().get_schedule(resource.id))
|
87
|
+
else:
|
88
|
+
raise RuntimeError(f"Unknown resource type: {resource.type}")
|
89
|
+
|
90
|
+
batch_verify_permissions_for_models(
|
91
|
+
models=verify_models,
|
92
|
+
action=Action.UPDATE,
|
93
|
+
)
|
94
|
+
|
95
|
+
verify_permission_for_model(model=run_metadata, action=Action.CREATE)
|
96
|
+
|
97
|
+
zen_store().create_run_metadata(run_metadata)
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for run templates."""
|
15
15
|
|
16
|
-
from typing import Optional
|
16
|
+
from typing import Optional, Union
|
17
17
|
from uuid import UUID
|
18
18
|
|
19
19
|
from fastapi import APIRouter, BackgroundTasks, Depends, Security
|
@@ -26,12 +26,14 @@ from zenml.models import (
|
|
26
26
|
Page,
|
27
27
|
PipelineRunResponse,
|
28
28
|
RunTemplateFilter,
|
29
|
+
RunTemplateRequest,
|
29
30
|
RunTemplateResponse,
|
30
31
|
RunTemplateUpdate,
|
31
32
|
)
|
32
33
|
from zenml.zen_server.auth import AuthContext, authorize
|
33
34
|
from zenml.zen_server.exceptions import error_response
|
34
35
|
from zenml.zen_server.rbac.endpoint_utils import (
|
36
|
+
verify_permissions_and_create_entity,
|
35
37
|
verify_permissions_and_delete_entity,
|
36
38
|
verify_permissions_and_get_entity,
|
37
39
|
verify_permissions_and_list_entities,
|
@@ -39,6 +41,7 @@ from zenml.zen_server.rbac.endpoint_utils import (
|
|
39
41
|
)
|
40
42
|
from zenml.zen_server.rbac.models import Action, ResourceType
|
41
43
|
from zenml.zen_server.rbac.utils import verify_permission
|
44
|
+
from zenml.zen_server.routers.projects_endpoints import workspace_router
|
42
45
|
from zenml.zen_server.utils import (
|
43
46
|
handle_exceptions,
|
44
47
|
make_dependable,
|
@@ -53,15 +56,61 @@ router = APIRouter(
|
|
53
56
|
)
|
54
57
|
|
55
58
|
|
59
|
+
@router.post(
|
60
|
+
"",
|
61
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
62
|
+
)
|
63
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
64
|
+
# and can be removed after the migration
|
65
|
+
@workspace_router.post(
|
66
|
+
"/{project_name_or_id}" + RUN_TEMPLATES,
|
67
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
68
|
+
deprecated=True,
|
69
|
+
tags=["run_templates"],
|
70
|
+
)
|
71
|
+
@handle_exceptions
|
72
|
+
def create_run_template(
|
73
|
+
run_template: RunTemplateRequest,
|
74
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
75
|
+
_: AuthContext = Security(authorize),
|
76
|
+
) -> RunTemplateResponse:
|
77
|
+
"""Create a run template.
|
78
|
+
|
79
|
+
Args:
|
80
|
+
run_template: Run template to create.
|
81
|
+
project_name_or_id: Optional name or ID of the project.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
The created run template.
|
85
|
+
"""
|
86
|
+
if project_name_or_id:
|
87
|
+
project = zen_store().get_project(project_name_or_id)
|
88
|
+
run_template.project = project.id
|
89
|
+
|
90
|
+
return verify_permissions_and_create_entity(
|
91
|
+
request_model=run_template,
|
92
|
+
create_method=zen_store().create_run_template,
|
93
|
+
)
|
94
|
+
|
95
|
+
|
56
96
|
@router.get(
|
57
97
|
"",
|
58
98
|
responses={401: error_response, 404: error_response, 422: error_response},
|
59
99
|
)
|
100
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
101
|
+
# and can be removed after the migration
|
102
|
+
@workspace_router.get(
|
103
|
+
"/{project_name_or_id}" + RUN_TEMPLATES,
|
104
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
105
|
+
deprecated=True,
|
106
|
+
tags=["run_templates"],
|
107
|
+
)
|
60
108
|
@handle_exceptions
|
61
109
|
def list_run_templates(
|
62
110
|
filter_model: RunTemplateFilter = Depends(
|
63
111
|
make_dependable(RunTemplateFilter)
|
64
112
|
),
|
113
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
65
114
|
hydrate: bool = False,
|
66
115
|
_: AuthContext = Security(authorize),
|
67
116
|
) -> Page[RunTemplateResponse]:
|
@@ -70,12 +119,16 @@ def list_run_templates(
|
|
70
119
|
Args:
|
71
120
|
filter_model: Filter model used for pagination, sorting,
|
72
121
|
filtering.
|
122
|
+
project_name_or_id: Optional name or ID of the project.
|
73
123
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
74
124
|
by including metadata fields in the response.
|
75
125
|
|
76
126
|
Returns:
|
77
127
|
Page of run templates.
|
78
128
|
"""
|
129
|
+
if project_name_or_id:
|
130
|
+
filter_model.project = project_name_or_id
|
131
|
+
|
79
132
|
return verify_permissions_and_list_entities(
|
80
133
|
filter_model=filter_model,
|
81
134
|
resource_type=ResourceType.RUN_TEMPLATE,
|
@@ -189,19 +242,27 @@ if server_config().workload_manager_enabled:
|
|
189
242
|
"""
|
190
243
|
from zenml.zen_server.template_execution.utils import run_template
|
191
244
|
|
192
|
-
with track_handler(
|
245
|
+
with track_handler(
|
246
|
+
event=AnalyticsEvent.EXECUTED_RUN_TEMPLATE,
|
247
|
+
) as analytics_handler:
|
193
248
|
template = verify_permissions_and_get_entity(
|
194
249
|
id=template_id,
|
195
250
|
get_method=zen_store().get_run_template,
|
196
251
|
hydrate=True,
|
197
252
|
)
|
253
|
+
analytics_handler.metadata = {
|
254
|
+
"project_id": template.project.id,
|
255
|
+
}
|
198
256
|
|
199
257
|
verify_permission(
|
200
258
|
resource_type=ResourceType.PIPELINE_DEPLOYMENT,
|
201
259
|
action=Action.CREATE,
|
260
|
+
project_id=template.project.id,
|
202
261
|
)
|
203
262
|
verify_permission(
|
204
|
-
resource_type=ResourceType.PIPELINE_RUN,
|
263
|
+
resource_type=ResourceType.PIPELINE_RUN,
|
264
|
+
action=Action.CREATE,
|
265
|
+
project_id=template.project.id,
|
205
266
|
)
|
206
267
|
|
207
268
|
return run_template(
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for pipeline runs."""
|
15
15
|
|
16
|
-
from typing import Any, Dict
|
16
|
+
from typing import Any, Dict, Optional, Tuple, Union
|
17
17
|
from uuid import UUID
|
18
18
|
|
19
19
|
from fastapi import APIRouter, Depends, Security
|
@@ -32,6 +32,7 @@ from zenml.logger import get_logger
|
|
32
32
|
from zenml.models import (
|
33
33
|
Page,
|
34
34
|
PipelineRunFilter,
|
35
|
+
PipelineRunRequest,
|
35
36
|
PipelineRunResponse,
|
36
37
|
PipelineRunUpdate,
|
37
38
|
StepRunFilter,
|
@@ -42,11 +43,15 @@ from zenml.zen_server.exceptions import error_response
|
|
42
43
|
from zenml.zen_server.rbac.endpoint_utils import (
|
43
44
|
verify_permissions_and_delete_entity,
|
44
45
|
verify_permissions_and_get_entity,
|
46
|
+
verify_permissions_and_get_or_create_entity,
|
45
47
|
verify_permissions_and_list_entities,
|
46
48
|
verify_permissions_and_update_entity,
|
47
49
|
)
|
48
50
|
from zenml.zen_server.rbac.models import Action, ResourceType
|
49
|
-
from zenml.zen_server.rbac.utils import
|
51
|
+
from zenml.zen_server.rbac.utils import (
|
52
|
+
verify_permission_for_model,
|
53
|
+
)
|
54
|
+
from zenml.zen_server.routers.projects_endpoints import workspace_router
|
50
55
|
from zenml.zen_server.utils import (
|
51
56
|
handle_exceptions,
|
52
57
|
make_dependable,
|
@@ -63,16 +68,62 @@ router = APIRouter(
|
|
63
68
|
logger = get_logger(__name__)
|
64
69
|
|
65
70
|
|
71
|
+
@router.post(
|
72
|
+
"",
|
73
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
74
|
+
)
|
75
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
76
|
+
# and can be removed after the migration
|
77
|
+
@workspace_router.post(
|
78
|
+
"/{project_name_or_id}" + RUNS,
|
79
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
80
|
+
deprecated=True,
|
81
|
+
tags=["runs"],
|
82
|
+
)
|
83
|
+
@handle_exceptions
|
84
|
+
def get_or_create_pipeline_run(
|
85
|
+
pipeline_run: PipelineRunRequest,
|
86
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
87
|
+
_: AuthContext = Security(authorize),
|
88
|
+
) -> Tuple[PipelineRunResponse, bool]:
|
89
|
+
"""Get or create a pipeline run.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
pipeline_run: Pipeline run to create.
|
93
|
+
project_name_or_id: Optional name or ID of the project.
|
94
|
+
|
95
|
+
Returns:
|
96
|
+
The pipeline run and a boolean indicating whether the run was created
|
97
|
+
or not.
|
98
|
+
"""
|
99
|
+
if project_name_or_id:
|
100
|
+
project = zen_store().get_project(project_name_or_id)
|
101
|
+
pipeline_run.project = project.id
|
102
|
+
|
103
|
+
return verify_permissions_and_get_or_create_entity(
|
104
|
+
request_model=pipeline_run,
|
105
|
+
get_or_create_method=zen_store().get_or_create_run,
|
106
|
+
)
|
107
|
+
|
108
|
+
|
66
109
|
@router.get(
|
67
110
|
"",
|
68
|
-
response_model=Page[PipelineRunResponse],
|
69
111
|
responses={401: error_response, 404: error_response, 422: error_response},
|
70
112
|
)
|
113
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
114
|
+
# and can be removed after the migration
|
115
|
+
@workspace_router.get(
|
116
|
+
"/{project_name_or_id}" + RUNS,
|
117
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
118
|
+
deprecated=True,
|
119
|
+
tags=["runs"],
|
120
|
+
)
|
71
121
|
@handle_exceptions
|
72
122
|
def list_runs(
|
73
123
|
runs_filter_model: PipelineRunFilter = Depends(
|
74
124
|
make_dependable(PipelineRunFilter)
|
75
125
|
),
|
126
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
76
127
|
hydrate: bool = False,
|
77
128
|
_: AuthContext = Security(authorize),
|
78
129
|
) -> Page[PipelineRunResponse]:
|
@@ -80,12 +131,16 @@ def list_runs(
|
|
80
131
|
|
81
132
|
Args:
|
82
133
|
runs_filter_model: Filter model used for pagination, sorting, filtering.
|
134
|
+
project_name_or_id: Optional name or ID of the project.
|
83
135
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
84
136
|
by including metadata fields in the response.
|
85
137
|
|
86
138
|
Returns:
|
87
139
|
The pipeline runs according to query filters.
|
88
140
|
"""
|
141
|
+
if project_name_or_id:
|
142
|
+
runs_filter_model.project = project_name_or_id
|
143
|
+
|
89
144
|
return verify_permissions_and_list_entities(
|
90
145
|
filter_model=runs_filter_model,
|
91
146
|
resource_type=ResourceType.PIPELINE_RUN,
|
@@ -96,7 +151,6 @@ def list_runs(
|
|
96
151
|
|
97
152
|
@router.get(
|
98
153
|
"/{run_id}",
|
99
|
-
response_model=PipelineRunResponse,
|
100
154
|
responses={401: error_response, 404: error_response, 422: error_response},
|
101
155
|
)
|
102
156
|
@handle_exceptions
|
@@ -157,7 +211,6 @@ def get_run(
|
|
157
211
|
|
158
212
|
@router.put(
|
159
213
|
"/{run_id}",
|
160
|
-
response_model=PipelineRunResponse,
|
161
214
|
responses={401: error_response, 404: error_response, 422: error_response},
|
162
215
|
)
|
163
216
|
@handle_exceptions
|
@@ -206,7 +259,6 @@ def delete_run(
|
|
206
259
|
|
207
260
|
@router.get(
|
208
261
|
"/{run_id}" + STEPS,
|
209
|
-
response_model=Page[StepRunResponse],
|
210
262
|
responses={401: error_response, 404: error_response, 422: error_response},
|
211
263
|
)
|
212
264
|
@handle_exceptions
|
@@ -236,7 +288,6 @@ def get_run_steps(
|
|
236
288
|
|
237
289
|
@router.get(
|
238
290
|
"/{run_id}" + PIPELINE_CONFIGURATION,
|
239
|
-
response_model=Dict[str, Any],
|
240
291
|
responses={401: error_response, 404: error_response, 422: error_response},
|
241
292
|
)
|
242
293
|
@handle_exceptions
|
@@ -260,7 +311,6 @@ def get_pipeline_configuration(
|
|
260
311
|
|
261
312
|
@router.get(
|
262
313
|
"/{run_id}" + STATUS,
|
263
|
-
response_model=ExecutionStatus,
|
264
314
|
responses={401: error_response, 404: error_response, 422: error_response},
|
265
315
|
)
|
266
316
|
@handle_exceptions
|