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.
Files changed (191) hide show
  1. zenml/VERSION +1 -1
  2. zenml/__init__.py +2 -0
  3. zenml/analytics/context.py +7 -0
  4. zenml/analytics/enums.py +2 -2
  5. zenml/artifacts/utils.py +2 -4
  6. zenml/cli/__init__.py +8 -9
  7. zenml/cli/base.py +2 -2
  8. zenml/cli/code_repository.py +1 -1
  9. zenml/cli/login.py +6 -0
  10. zenml/cli/model.py +7 -15
  11. zenml/cli/pipeline.py +3 -3
  12. zenml/cli/project.py +172 -0
  13. zenml/cli/secret.py +47 -44
  14. zenml/cli/service_accounts.py +0 -1
  15. zenml/cli/service_connectors.py +15 -17
  16. zenml/cli/stack.py +0 -3
  17. zenml/cli/stack_components.py +2 -2
  18. zenml/cli/tag.py +3 -5
  19. zenml/cli/utils.py +25 -23
  20. zenml/client.py +749 -475
  21. zenml/config/global_config.py +48 -37
  22. zenml/config/pipeline_configurations.py +3 -2
  23. zenml/config/pipeline_run_configuration.py +2 -1
  24. zenml/config/secret_reference_mixin.py +1 -1
  25. zenml/constants.py +6 -6
  26. zenml/enums.py +0 -7
  27. zenml/event_hub/event_hub.py +3 -1
  28. zenml/exceptions.py +0 -24
  29. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +5 -3
  30. zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +1 -4
  31. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +7 -6
  32. zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +1 -4
  33. zenml/integrations/mlflow/steps/mlflow_registry.py +3 -3
  34. zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -1
  35. zenml/integrations/wandb/__init__.py +1 -1
  36. zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py +29 -9
  37. zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +5 -3
  38. zenml/model/model.py +10 -10
  39. zenml/model_registries/base_model_registry.py +1 -1
  40. zenml/models/__init__.py +45 -28
  41. zenml/models/v2/base/base.py +0 -5
  42. zenml/models/v2/base/filter.py +2 -2
  43. zenml/models/v2/base/scoped.py +135 -156
  44. zenml/models/v2/core/action.py +12 -12
  45. zenml/models/v2/core/api_key.py +1 -1
  46. zenml/models/v2/core/artifact.py +31 -18
  47. zenml/models/v2/core/artifact_version.py +57 -40
  48. zenml/models/v2/core/code_repository.py +12 -12
  49. zenml/models/v2/core/component.py +22 -33
  50. zenml/models/v2/core/device.py +3 -2
  51. zenml/models/v2/core/event_source.py +14 -14
  52. zenml/models/v2/core/flavor.py +19 -47
  53. zenml/models/v2/core/logs.py +1 -2
  54. zenml/models/v2/core/model.py +23 -20
  55. zenml/models/v2/core/model_version.py +51 -42
  56. zenml/models/v2/core/pipeline.py +16 -16
  57. zenml/models/v2/core/pipeline_build.py +14 -14
  58. zenml/models/v2/core/pipeline_deployment.py +12 -14
  59. zenml/models/v2/core/pipeline_run.py +21 -29
  60. zenml/models/v2/core/project.py +203 -0
  61. zenml/models/v2/core/run_metadata.py +2 -2
  62. zenml/models/v2/core/run_template.py +16 -17
  63. zenml/models/v2/core/schedule.py +12 -21
  64. zenml/models/v2/core/secret.py +94 -128
  65. zenml/models/v2/core/server_settings.py +2 -2
  66. zenml/models/v2/core/service.py +57 -26
  67. zenml/models/v2/core/service_connector.py +14 -16
  68. zenml/models/v2/core/stack.py +24 -26
  69. zenml/models/v2/core/step_run.py +16 -28
  70. zenml/models/v2/core/tag.py +41 -15
  71. zenml/models/v2/core/trigger.py +13 -13
  72. zenml/models/v2/core/trigger_execution.py +2 -2
  73. zenml/models/v2/core/user.py +2 -2
  74. zenml/models/v2/misc/statistics.py +45 -0
  75. zenml/models/v2/misc/tag.py +27 -0
  76. zenml/orchestrators/cache_utils.py +7 -7
  77. zenml/orchestrators/input_utils.py +1 -0
  78. zenml/orchestrators/step_launcher.py +1 -2
  79. zenml/orchestrators/step_run_utils.py +2 -4
  80. zenml/orchestrators/step_runner.py +10 -1
  81. zenml/orchestrators/utils.py +4 -4
  82. zenml/pipelines/build_utils.py +2 -4
  83. zenml/pipelines/pipeline_decorator.py +3 -2
  84. zenml/pipelines/pipeline_definition.py +8 -9
  85. zenml/pipelines/run_utils.py +4 -4
  86. zenml/service_connectors/service_connector.py +0 -10
  87. zenml/service_connectors/service_connector_utils.py +0 -2
  88. zenml/stack/authentication_mixin.py +1 -1
  89. zenml/stack/flavor.py +3 -14
  90. zenml/stack/stack.py +0 -1
  91. zenml/stack/stack_component.py +1 -5
  92. zenml/steps/base_step.py +10 -2
  93. zenml/steps/step_context.py +19 -0
  94. zenml/utils/string_utils.py +1 -1
  95. zenml/utils/tag_utils.py +642 -0
  96. zenml/zen_server/cloud_utils.py +21 -0
  97. zenml/zen_server/exceptions.py +0 -6
  98. zenml/zen_server/rbac/endpoint_utils.py +134 -46
  99. zenml/zen_server/rbac/models.py +65 -3
  100. zenml/zen_server/rbac/rbac_interface.py +9 -0
  101. zenml/zen_server/rbac/rbac_sql_zen_store.py +15 -7
  102. zenml/zen_server/rbac/utils.py +155 -30
  103. zenml/zen_server/rbac/zenml_cloud_rbac.py +39 -11
  104. zenml/zen_server/routers/actions_endpoints.py +3 -5
  105. zenml/zen_server/routers/artifact_endpoint.py +0 -5
  106. zenml/zen_server/routers/artifact_version_endpoints.py +15 -9
  107. zenml/zen_server/routers/auth_endpoints.py +22 -7
  108. zenml/zen_server/routers/code_repositories_endpoints.py +54 -3
  109. zenml/zen_server/routers/devices_endpoints.py +0 -4
  110. zenml/zen_server/routers/event_source_endpoints.py +0 -5
  111. zenml/zen_server/routers/flavors_endpoints.py +0 -5
  112. zenml/zen_server/routers/logs_endpoints.py +0 -1
  113. zenml/zen_server/routers/model_versions_endpoints.py +100 -23
  114. zenml/zen_server/routers/models_endpoints.py +50 -69
  115. zenml/zen_server/routers/pipeline_builds_endpoints.py +55 -3
  116. zenml/zen_server/routers/pipeline_deployments_endpoints.py +56 -4
  117. zenml/zen_server/routers/pipelines_endpoints.py +70 -3
  118. zenml/zen_server/routers/plugin_endpoints.py +0 -1
  119. zenml/zen_server/routers/projects_endpoints.py +283 -0
  120. zenml/zen_server/routers/run_metadata_endpoints.py +97 -0
  121. zenml/zen_server/routers/run_templates_endpoints.py +64 -3
  122. zenml/zen_server/routers/runs_endpoints.py +58 -8
  123. zenml/zen_server/routers/schedule_endpoints.py +67 -6
  124. zenml/zen_server/routers/secrets_endpoints.py +38 -4
  125. zenml/zen_server/routers/server_endpoints.py +53 -1
  126. zenml/zen_server/routers/service_accounts_endpoints.py +14 -15
  127. zenml/zen_server/routers/service_connectors_endpoints.py +94 -14
  128. zenml/zen_server/routers/service_endpoints.py +18 -7
  129. zenml/zen_server/routers/stack_components_endpoints.py +66 -7
  130. zenml/zen_server/routers/stacks_endpoints.py +95 -6
  131. zenml/zen_server/routers/steps_endpoints.py +17 -11
  132. zenml/zen_server/routers/tag_resource_endpoints.py +115 -0
  133. zenml/zen_server/routers/tags_endpoints.py +6 -17
  134. zenml/zen_server/routers/triggers_endpoints.py +5 -8
  135. zenml/zen_server/routers/users_endpoints.py +9 -12
  136. zenml/zen_server/template_execution/utils.py +8 -7
  137. zenml/zen_server/utils.py +21 -0
  138. zenml/zen_server/zen_server_api.py +7 -2
  139. zenml/zen_stores/base_zen_store.py +50 -69
  140. zenml/zen_stores/migrations/versions/12eff0206201_rename_workspace_to_project.py +768 -0
  141. zenml/zen_stores/migrations/versions/1cb6477f72d6_move_artifact_save_type.py +20 -10
  142. zenml/zen_stores/migrations/versions/1f9d1cd00b90_add_unique_name_constraints.py +231 -0
  143. zenml/zen_stores/migrations/versions/288f4fb6e112_make_tags_user_scoped.py +74 -0
  144. zenml/zen_stores/migrations/versions/2e695a26fe7a_add_user_default_workspace.py +45 -0
  145. zenml/zen_stores/migrations/versions/3b1776345020_remove_workspace_from_globals.py +81 -0
  146. zenml/zen_stores/migrations/versions/41b28cae31ce_make_artifacts_workspace_scoped.py +136 -0
  147. zenml/zen_stores/migrations/versions/9e7bf0970266_adding_exclusive_attribute_to_tags.py +47 -0
  148. zenml/zen_stores/migrations/versions/b557b2871693_update_step_run_input_types.py +8 -4
  149. zenml/zen_stores/migrations/versions/cbc6acd71f92_add_workspace_display_name.py +58 -0
  150. zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +12 -6
  151. zenml/zen_stores/migrations/versions/f1d723fd723b_add_secret_private_attr.py +61 -0
  152. zenml/zen_stores/migrations/versions/f76a368a25a5_add_stack_description.py +35 -0
  153. zenml/zen_stores/rest_zen_store.py +223 -230
  154. zenml/zen_stores/schemas/__init__.py +2 -2
  155. zenml/zen_stores/schemas/action_schemas.py +15 -8
  156. zenml/zen_stores/schemas/api_key_schemas.py +8 -1
  157. zenml/zen_stores/schemas/artifact_schemas.py +35 -10
  158. zenml/zen_stores/schemas/code_repository_schemas.py +22 -17
  159. zenml/zen_stores/schemas/component_schemas.py +9 -14
  160. zenml/zen_stores/schemas/event_source_schemas.py +15 -8
  161. zenml/zen_stores/schemas/flavor_schemas.py +14 -20
  162. zenml/zen_stores/schemas/model_schemas.py +18 -17
  163. zenml/zen_stores/schemas/pipeline_build_schemas.py +7 -7
  164. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +10 -8
  165. zenml/zen_stores/schemas/pipeline_run_schemas.py +9 -12
  166. zenml/zen_stores/schemas/pipeline_schemas.py +9 -9
  167. zenml/zen_stores/schemas/{workspace_schemas.py → project_schemas.py} +53 -65
  168. zenml/zen_stores/schemas/run_metadata_schemas.py +5 -5
  169. zenml/zen_stores/schemas/run_template_schemas.py +17 -13
  170. zenml/zen_stores/schemas/schedule_schema.py +16 -21
  171. zenml/zen_stores/schemas/secret_schemas.py +15 -25
  172. zenml/zen_stores/schemas/service_connector_schemas.py +8 -17
  173. zenml/zen_stores/schemas/service_schemas.py +7 -8
  174. zenml/zen_stores/schemas/stack_schemas.py +12 -15
  175. zenml/zen_stores/schemas/step_run_schemas.py +14 -15
  176. zenml/zen_stores/schemas/tag_schemas.py +30 -2
  177. zenml/zen_stores/schemas/trigger_schemas.py +15 -8
  178. zenml/zen_stores/schemas/user_schemas.py +12 -2
  179. zenml/zen_stores/schemas/utils.py +16 -0
  180. zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +0 -3
  181. zenml/zen_stores/sql_zen_store.py +2984 -2369
  182. zenml/zen_stores/template_utils.py +1 -1
  183. zenml/zen_stores/zen_store_interface.py +136 -126
  184. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/METADATA +1 -1
  185. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/RECORD +188 -173
  186. zenml/cli/workspace.py +0 -86
  187. zenml/models/v2/core/workspace.py +0 -131
  188. zenml/zen_server/routers/workspaces_endpoints.py +0 -1469
  189. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/LICENSE +0 -0
  190. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/WHEEL +0 -0
  191. {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(event=AnalyticsEvent.EXECUTED_RUN_TEMPLATE):
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, action=Action.CREATE
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 verify_permission_for_model
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