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
@@ -1,1469 +0,0 @@
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 workspaces."""
15
-
16
- from typing import Any, Dict, List, Optional, Tuple, Union
17
- from uuid import UUID
18
-
19
- from fastapi import APIRouter, Depends, Security
20
-
21
- from zenml.constants import (
22
- API,
23
- CODE_REPOSITORIES,
24
- GET_OR_CREATE,
25
- MODEL_VERSIONS,
26
- MODELS,
27
- PIPELINE_BUILDS,
28
- PIPELINE_DEPLOYMENTS,
29
- PIPELINES,
30
- RUN_METADATA,
31
- RUN_TEMPLATES,
32
- RUNS,
33
- SCHEDULES,
34
- SECRETS,
35
- SERVICE_CONNECTOR_RESOURCES,
36
- SERVICE_CONNECTORS,
37
- SERVICES,
38
- STACK_COMPONENTS,
39
- STACKS,
40
- STATISTICS,
41
- VERSION_1,
42
- WORKSPACES,
43
- )
44
- from zenml.enums import MetadataResourceTypes
45
- from zenml.exceptions import IllegalOperationError
46
- from zenml.models import (
47
- CodeRepositoryFilter,
48
- CodeRepositoryRequest,
49
- CodeRepositoryResponse,
50
- ComponentFilter,
51
- ComponentRequest,
52
- ComponentResponse,
53
- ModelRequest,
54
- ModelResponse,
55
- ModelVersionRequest,
56
- ModelVersionResponse,
57
- Page,
58
- PipelineBuildFilter,
59
- PipelineBuildRequest,
60
- PipelineBuildResponse,
61
- PipelineDeploymentFilter,
62
- PipelineDeploymentRequest,
63
- PipelineDeploymentResponse,
64
- PipelineFilter,
65
- PipelineRequest,
66
- PipelineResponse,
67
- PipelineRunFilter,
68
- PipelineRunRequest,
69
- PipelineRunResponse,
70
- RunMetadataRequest,
71
- RunTemplateFilter,
72
- RunTemplateRequest,
73
- RunTemplateResponse,
74
- ScheduleRequest,
75
- ScheduleResponse,
76
- SecretRequest,
77
- SecretResponse,
78
- ServiceConnectorFilter,
79
- ServiceConnectorRequest,
80
- ServiceConnectorResourcesModel,
81
- ServiceConnectorResponse,
82
- ServiceRequest,
83
- ServiceResponse,
84
- StackFilter,
85
- StackRequest,
86
- StackResponse,
87
- WorkspaceFilter,
88
- WorkspaceRequest,
89
- WorkspaceResponse,
90
- WorkspaceUpdate,
91
- )
92
- from zenml.zen_server.auth import AuthContext, authorize
93
- from zenml.zen_server.exceptions import error_response
94
- from zenml.zen_server.feature_gate.endpoint_utils import (
95
- check_entitlement,
96
- report_usage,
97
- )
98
- from zenml.zen_server.rbac.endpoint_utils import (
99
- verify_permissions_and_create_entity,
100
- verify_permissions_and_list_entities,
101
- )
102
- from zenml.zen_server.rbac.models import Action, ResourceType
103
- from zenml.zen_server.rbac.utils import (
104
- batch_verify_permissions_for_models,
105
- dehydrate_page,
106
- dehydrate_response_model,
107
- get_allowed_resource_ids,
108
- verify_permission,
109
- verify_permission_for_model,
110
- )
111
- from zenml.zen_server.utils import (
112
- handle_exceptions,
113
- make_dependable,
114
- server_config,
115
- zen_store,
116
- )
117
-
118
- router = APIRouter(
119
- prefix=API + VERSION_1,
120
- tags=["workspaces"],
121
- responses={401: error_response},
122
- )
123
-
124
-
125
- @router.get(
126
- WORKSPACES,
127
- response_model=Page[WorkspaceResponse],
128
- responses={401: error_response, 404: error_response, 422: error_response},
129
- )
130
- @handle_exceptions
131
- def list_workspaces(
132
- workspace_filter_model: WorkspaceFilter = Depends(
133
- make_dependable(WorkspaceFilter)
134
- ),
135
- hydrate: bool = False,
136
- _: AuthContext = Security(authorize),
137
- ) -> Page[WorkspaceResponse]:
138
- """Lists all workspaces in the organization.
139
-
140
- Args:
141
- workspace_filter_model: Filter model used for pagination, sorting,
142
- filtering,
143
- hydrate: Flag deciding whether to hydrate the output model(s)
144
- by including metadata fields in the response.
145
-
146
- Returns:
147
- A list of workspaces.
148
- """
149
- workspaces = zen_store().list_workspaces(
150
- workspace_filter_model, hydrate=hydrate
151
- )
152
- return dehydrate_page(workspaces)
153
-
154
-
155
- @router.post(
156
- WORKSPACES,
157
- responses={401: error_response, 409: error_response, 422: error_response},
158
- )
159
- @handle_exceptions
160
- def create_workspace(
161
- workspace_request: WorkspaceRequest,
162
- _: AuthContext = Security(authorize),
163
- ) -> WorkspaceResponse:
164
- """Creates a workspace based on the requestBody.
165
-
166
- # noqa: DAR401
167
-
168
- Args:
169
- workspace_request: Workspace to create.
170
-
171
- Returns:
172
- The created workspace.
173
- """
174
- workspace = zen_store().create_workspace(workspace_request)
175
- return dehydrate_response_model(workspace)
176
-
177
-
178
- @router.get(
179
- WORKSPACES + "/{workspace_name_or_id}",
180
- response_model=WorkspaceResponse,
181
- responses={401: error_response, 404: error_response, 422: error_response},
182
- )
183
- @handle_exceptions
184
- def get_workspace(
185
- workspace_name_or_id: Union[str, UUID],
186
- hydrate: bool = True,
187
- _: AuthContext = Security(authorize),
188
- ) -> WorkspaceResponse:
189
- """Get a workspace for given name.
190
-
191
- # noqa: DAR401
192
-
193
- Args:
194
- workspace_name_or_id: Name or ID of the workspace.
195
- hydrate: Flag deciding whether to hydrate the output model(s)
196
- by including metadata fields in the response.
197
-
198
- Returns:
199
- The requested workspace.
200
- """
201
- workspace = zen_store().get_workspace(
202
- workspace_name_or_id, hydrate=hydrate
203
- )
204
- return dehydrate_response_model(workspace)
205
-
206
-
207
- @router.put(
208
- WORKSPACES + "/{workspace_name_or_id}",
209
- responses={401: error_response, 404: error_response, 422: error_response},
210
- )
211
- @handle_exceptions
212
- def update_workspace(
213
- workspace_name_or_id: UUID,
214
- workspace_update: WorkspaceUpdate,
215
- _: AuthContext = Security(authorize),
216
- ) -> WorkspaceResponse:
217
- """Get a workspace for given name.
218
-
219
- # noqa: DAR401
220
-
221
- Args:
222
- workspace_name_or_id: Name or ID of the workspace to update.
223
- workspace_update: the workspace to use to update
224
-
225
- Returns:
226
- The updated workspace.
227
- """
228
- workspace = zen_store().get_workspace(workspace_name_or_id, hydrate=False)
229
- updated_workspace = zen_store().update_workspace(
230
- workspace_id=workspace.id, workspace_update=workspace_update
231
- )
232
- return dehydrate_response_model(updated_workspace)
233
-
234
-
235
- @router.delete(
236
- WORKSPACES + "/{workspace_name_or_id}",
237
- responses={401: error_response, 404: error_response, 422: error_response},
238
- )
239
- @handle_exceptions
240
- def delete_workspace(
241
- workspace_name_or_id: Union[str, UUID],
242
- _: AuthContext = Security(authorize),
243
- ) -> None:
244
- """Deletes a workspace.
245
-
246
- Args:
247
- workspace_name_or_id: Name or ID of the workspace.
248
- """
249
- zen_store().delete_workspace(workspace_name_or_id)
250
-
251
-
252
- @router.get(
253
- WORKSPACES + "/{workspace_name_or_id}" + STACKS,
254
- response_model=Page[StackResponse],
255
- responses={401: error_response, 404: error_response, 422: error_response},
256
- )
257
- @handle_exceptions
258
- def list_workspace_stacks(
259
- workspace_name_or_id: Union[str, UUID],
260
- stack_filter_model: StackFilter = Depends(make_dependable(StackFilter)),
261
- hydrate: bool = False,
262
- _: AuthContext = Security(authorize),
263
- ) -> Page[StackResponse]:
264
- """Get stacks that are part of a specific workspace for the user.
265
-
266
- # noqa: DAR401
267
-
268
- Args:
269
- workspace_name_or_id: Name or ID of the workspace.
270
- stack_filter_model: Filter model used for pagination, sorting,
271
- filtering.
272
- hydrate: Flag deciding whether to hydrate the output model(s)
273
- by including metadata fields in the response.
274
-
275
- Returns:
276
- All stacks part of the specified workspace.
277
- """
278
- workspace = zen_store().get_workspace(workspace_name_or_id)
279
- stack_filter_model.set_scope_workspace(workspace.id)
280
-
281
- return verify_permissions_and_list_entities(
282
- filter_model=stack_filter_model,
283
- resource_type=ResourceType.STACK,
284
- list_method=zen_store().list_stacks,
285
- hydrate=hydrate,
286
- )
287
-
288
-
289
- @router.post(
290
- WORKSPACES + "/{workspace_name_or_id}" + STACKS,
291
- response_model=StackResponse,
292
- responses={401: error_response, 409: error_response, 422: error_response},
293
- )
294
- @handle_exceptions
295
- def create_stack(
296
- workspace_name_or_id: Union[str, UUID],
297
- stack: StackRequest,
298
- auth_context: AuthContext = Security(authorize),
299
- ) -> StackResponse:
300
- """Creates a stack for a particular workspace.
301
-
302
- Args:
303
- workspace_name_or_id: Name or ID of the workspace.
304
- stack: Stack to register.
305
- auth_context: Authentication context.
306
-
307
- Returns:
308
- The created stack.
309
- """
310
- workspace = zen_store().get_workspace(workspace_name_or_id)
311
-
312
- # Check the service connector creation
313
- is_connector_create_needed = False
314
- for connector_id_or_info in stack.service_connectors:
315
- if isinstance(connector_id_or_info, UUID):
316
- service_connector = zen_store().get_service_connector(
317
- connector_id_or_info, hydrate=False
318
- )
319
- verify_permission_for_model(
320
- model=service_connector, action=Action.READ
321
- )
322
- else:
323
- is_connector_create_needed = True
324
-
325
- # Check the component creation
326
- if is_connector_create_needed:
327
- verify_permission(
328
- resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
329
- )
330
- is_component_create_needed = False
331
- for components in stack.components.values():
332
- for component_id_or_info in components:
333
- if isinstance(component_id_or_info, UUID):
334
- component = zen_store().get_stack_component(
335
- component_id_or_info, hydrate=False
336
- )
337
- verify_permission_for_model(
338
- model=component, action=Action.READ
339
- )
340
- else:
341
- is_component_create_needed = True
342
- if is_component_create_needed:
343
- verify_permission(
344
- resource_type=ResourceType.STACK_COMPONENT,
345
- action=Action.CREATE,
346
- )
347
-
348
- # Check the stack creation
349
- verify_permission(resource_type=ResourceType.STACK, action=Action.CREATE)
350
-
351
- stack.user = auth_context.user.id
352
- stack.workspace = workspace.id
353
-
354
- return zen_store().create_stack(stack)
355
-
356
-
357
- @router.get(
358
- WORKSPACES + "/{workspace_name_or_id}" + STACK_COMPONENTS,
359
- response_model=Page[ComponentResponse],
360
- responses={401: error_response, 404: error_response, 422: error_response},
361
- )
362
- @handle_exceptions
363
- def list_workspace_stack_components(
364
- workspace_name_or_id: Union[str, UUID],
365
- component_filter_model: ComponentFilter = Depends(
366
- make_dependable(ComponentFilter)
367
- ),
368
- hydrate: bool = False,
369
- _: AuthContext = Security(authorize),
370
- ) -> Page[ComponentResponse]:
371
- """List stack components that are part of a specific workspace.
372
-
373
- # noqa: DAR401
374
-
375
- Args:
376
- workspace_name_or_id: Name or ID of the workspace.
377
- component_filter_model: Filter model used for pagination, sorting,
378
- filtering.
379
- hydrate: Flag deciding whether to hydrate the output model(s)
380
- by including metadata fields in the response.
381
-
382
- Returns:
383
- All stack components part of the specified workspace.
384
- """
385
- workspace = zen_store().get_workspace(workspace_name_or_id)
386
- component_filter_model.set_scope_workspace(workspace.id)
387
-
388
- return verify_permissions_and_list_entities(
389
- filter_model=component_filter_model,
390
- resource_type=ResourceType.STACK_COMPONENT,
391
- list_method=zen_store().list_stack_components,
392
- hydrate=hydrate,
393
- )
394
-
395
-
396
- @router.post(
397
- WORKSPACES + "/{workspace_name_or_id}" + STACK_COMPONENTS,
398
- response_model=ComponentResponse,
399
- responses={401: error_response, 409: error_response, 422: error_response},
400
- )
401
- @handle_exceptions
402
- def create_stack_component(
403
- workspace_name_or_id: Union[str, UUID],
404
- component: ComponentRequest,
405
- _: AuthContext = Security(authorize),
406
- ) -> ComponentResponse:
407
- """Creates a stack component.
408
-
409
- Args:
410
- workspace_name_or_id: Name or ID of the workspace.
411
- component: Stack component to register.
412
-
413
- Returns:
414
- The created stack component.
415
-
416
- Raises:
417
- IllegalOperationError: If the workspace specified in the stack
418
- component does not match the current workspace.
419
- """
420
- workspace = zen_store().get_workspace(workspace_name_or_id)
421
-
422
- if component.workspace != workspace.id:
423
- raise IllegalOperationError(
424
- "Creating components outside of the workspace scope "
425
- f"of this endpoint `{workspace_name_or_id}` is "
426
- f"not supported."
427
- )
428
-
429
- if component.connector:
430
- service_connector = zen_store().get_service_connector(
431
- component.connector
432
- )
433
- verify_permission_for_model(service_connector, action=Action.READ)
434
-
435
- from zenml.stack.utils import validate_stack_component_config
436
-
437
- validate_stack_component_config(
438
- configuration_dict=component.configuration,
439
- flavor=component.flavor,
440
- component_type=component.type,
441
- zen_store=zen_store(),
442
- # We allow custom flavors to fail import on the server side.
443
- validate_custom_flavors=False,
444
- )
445
-
446
- return verify_permissions_and_create_entity(
447
- request_model=component,
448
- resource_type=ResourceType.STACK_COMPONENT,
449
- create_method=zen_store().create_stack_component,
450
- )
451
-
452
-
453
- @router.get(
454
- WORKSPACES + "/{workspace_name_or_id}" + PIPELINES,
455
- response_model=Page[PipelineResponse],
456
- responses={401: error_response, 404: error_response, 422: error_response},
457
- )
458
- @handle_exceptions
459
- def list_workspace_pipelines(
460
- workspace_name_or_id: Union[str, UUID],
461
- pipeline_filter_model: PipelineFilter = Depends(
462
- make_dependable(PipelineFilter)
463
- ),
464
- hydrate: bool = False,
465
- _: AuthContext = Security(authorize),
466
- ) -> Page[PipelineResponse]:
467
- """Gets pipelines defined for a specific workspace.
468
-
469
- # noqa: DAR401
470
-
471
- Args:
472
- workspace_name_or_id: Name or ID of the workspace.
473
- pipeline_filter_model: Filter model used for pagination, sorting,
474
- filtering.
475
- hydrate: Flag deciding whether to hydrate the output model(s)
476
- by including metadata fields in the response.
477
-
478
- Returns:
479
- All pipelines within the workspace.
480
- """
481
- workspace = zen_store().get_workspace(workspace_name_or_id)
482
- pipeline_filter_model.set_scope_workspace(workspace.id)
483
-
484
- return verify_permissions_and_list_entities(
485
- filter_model=pipeline_filter_model,
486
- resource_type=ResourceType.PIPELINE,
487
- list_method=zen_store().list_pipelines,
488
- hydrate=hydrate,
489
- )
490
-
491
-
492
- @router.post(
493
- WORKSPACES + "/{workspace_name_or_id}" + PIPELINES,
494
- response_model=PipelineResponse,
495
- responses={401: error_response, 409: error_response, 422: error_response},
496
- )
497
- @handle_exceptions
498
- def create_pipeline(
499
- workspace_name_or_id: Union[str, UUID],
500
- pipeline: PipelineRequest,
501
- _: AuthContext = Security(authorize),
502
- ) -> PipelineResponse:
503
- """Creates a pipeline.
504
-
505
- Args:
506
- workspace_name_or_id: Name or ID of the workspace.
507
- pipeline: Pipeline to create.
508
-
509
- Returns:
510
- The created pipeline.
511
-
512
- Raises:
513
- IllegalOperationError: If the workspace or user specified in the pipeline
514
- does not match the current workspace or authenticated user.
515
- """
516
- workspace = zen_store().get_workspace(workspace_name_or_id)
517
-
518
- if pipeline.workspace != workspace.id:
519
- raise IllegalOperationError(
520
- "Creating pipelines outside of the workspace scope "
521
- f"of this endpoint `{workspace_name_or_id}` is "
522
- f"not supported."
523
- )
524
-
525
- # We limit pipeline namespaces, not pipeline versions
526
- needs_usage_increment = (
527
- ResourceType.PIPELINE in server_config().reportable_resources
528
- and zen_store().count_pipelines(PipelineFilter(name=pipeline.name))
529
- == 0
530
- )
531
-
532
- if needs_usage_increment:
533
- check_entitlement(ResourceType.PIPELINE)
534
-
535
- pipeline_response = verify_permissions_and_create_entity(
536
- request_model=pipeline,
537
- resource_type=ResourceType.PIPELINE,
538
- create_method=zen_store().create_pipeline,
539
- )
540
-
541
- if needs_usage_increment:
542
- report_usage(
543
- resource_type=ResourceType.PIPELINE,
544
- resource_id=pipeline_response.id,
545
- )
546
-
547
- return pipeline_response
548
-
549
-
550
- @router.get(
551
- WORKSPACES + "/{workspace_name_or_id}" + PIPELINE_BUILDS,
552
- response_model=Page[PipelineBuildResponse],
553
- responses={401: error_response, 404: error_response, 422: error_response},
554
- )
555
- @handle_exceptions
556
- def list_workspace_builds(
557
- workspace_name_or_id: Union[str, UUID],
558
- build_filter_model: PipelineBuildFilter = Depends(
559
- make_dependable(PipelineBuildFilter)
560
- ),
561
- hydrate: bool = False,
562
- _: AuthContext = Security(authorize),
563
- ) -> Page[PipelineBuildResponse]:
564
- """Gets builds defined for a specific workspace.
565
-
566
- # noqa: DAR401
567
-
568
- Args:
569
- workspace_name_or_id: Name or ID of the workspace.
570
- build_filter_model: Filter model used for pagination, sorting,
571
- filtering.
572
- hydrate: Flag deciding whether to hydrate the output model(s)
573
- by including metadata fields in the response.
574
-
575
- Returns:
576
- All builds within the workspace.
577
- """
578
- workspace = zen_store().get_workspace(workspace_name_or_id)
579
- build_filter_model.set_scope_workspace(workspace.id)
580
-
581
- return verify_permissions_and_list_entities(
582
- filter_model=build_filter_model,
583
- resource_type=ResourceType.PIPELINE_BUILD,
584
- list_method=zen_store().list_builds,
585
- hydrate=hydrate,
586
- )
587
-
588
-
589
- @router.post(
590
- WORKSPACES + "/{workspace_name_or_id}" + PIPELINE_BUILDS,
591
- response_model=PipelineBuildResponse,
592
- responses={401: error_response, 409: error_response, 422: error_response},
593
- )
594
- @handle_exceptions
595
- def create_build(
596
- workspace_name_or_id: Union[str, UUID],
597
- build: PipelineBuildRequest,
598
- auth_context: AuthContext = Security(authorize),
599
- ) -> PipelineBuildResponse:
600
- """Creates a build.
601
-
602
- Args:
603
- workspace_name_or_id: Name or ID of the workspace.
604
- build: Build to create.
605
- auth_context: Authentication context.
606
-
607
- Returns:
608
- The created build.
609
-
610
- Raises:
611
- IllegalOperationError: If the workspace specified in the build
612
- does not match the current workspace.
613
- """
614
- workspace = zen_store().get_workspace(workspace_name_or_id)
615
-
616
- if build.workspace != workspace.id:
617
- raise IllegalOperationError(
618
- "Creating builds outside of the workspace scope "
619
- f"of this endpoint `{workspace_name_or_id}` is "
620
- f"not supported."
621
- )
622
-
623
- return verify_permissions_and_create_entity(
624
- request_model=build,
625
- resource_type=ResourceType.PIPELINE_BUILD,
626
- create_method=zen_store().create_build,
627
- )
628
-
629
-
630
- @router.get(
631
- WORKSPACES + "/{workspace_name_or_id}" + PIPELINE_DEPLOYMENTS,
632
- response_model=Page[PipelineDeploymentResponse],
633
- responses={401: error_response, 404: error_response, 422: error_response},
634
- )
635
- @handle_exceptions
636
- def list_workspace_deployments(
637
- workspace_name_or_id: Union[str, UUID],
638
- deployment_filter_model: PipelineDeploymentFilter = Depends(
639
- make_dependable(PipelineDeploymentFilter)
640
- ),
641
- hydrate: bool = False,
642
- _: AuthContext = Security(authorize),
643
- ) -> Page[PipelineDeploymentResponse]:
644
- """Gets deployments defined for a specific workspace.
645
-
646
- # noqa: DAR401
647
-
648
- Args:
649
- workspace_name_or_id: Name or ID of the workspace.
650
- deployment_filter_model: Filter model used for pagination, sorting,
651
- filtering.
652
- hydrate: Flag deciding whether to hydrate the output model(s)
653
- by including metadata fields in the response.
654
-
655
- Returns:
656
- All deployments within the workspace.
657
- """
658
- workspace = zen_store().get_workspace(workspace_name_or_id)
659
- deployment_filter_model.set_scope_workspace(workspace.id)
660
-
661
- return verify_permissions_and_list_entities(
662
- filter_model=deployment_filter_model,
663
- resource_type=ResourceType.PIPELINE_DEPLOYMENT,
664
- list_method=zen_store().list_deployments,
665
- hydrate=hydrate,
666
- )
667
-
668
-
669
- @router.post(
670
- WORKSPACES + "/{workspace_name_or_id}" + PIPELINE_DEPLOYMENTS,
671
- response_model=PipelineDeploymentResponse,
672
- responses={401: error_response, 409: error_response, 422: error_response},
673
- )
674
- @handle_exceptions
675
- def create_deployment(
676
- workspace_name_or_id: Union[str, UUID],
677
- deployment: PipelineDeploymentRequest,
678
- auth_context: AuthContext = Security(authorize),
679
- ) -> PipelineDeploymentResponse:
680
- """Creates a deployment.
681
-
682
- Args:
683
- workspace_name_or_id: Name or ID of the workspace.
684
- deployment: Deployment to create.
685
- auth_context: Authentication context.
686
-
687
- Returns:
688
- The created deployment.
689
-
690
- Raises:
691
- IllegalOperationError: If the workspace specified in the
692
- deployment does not match the current workspace.
693
- """
694
- workspace = zen_store().get_workspace(workspace_name_or_id)
695
-
696
- if deployment.workspace != workspace.id:
697
- raise IllegalOperationError(
698
- "Creating deployments outside of the workspace scope "
699
- f"of this endpoint `{workspace_name_or_id}` is "
700
- f"not supported."
701
- )
702
-
703
- return verify_permissions_and_create_entity(
704
- request_model=deployment,
705
- resource_type=ResourceType.PIPELINE_DEPLOYMENT,
706
- create_method=zen_store().create_deployment,
707
- )
708
-
709
-
710
- @router.get(
711
- WORKSPACES + "/{workspace_name_or_id}" + RUN_TEMPLATES,
712
- responses={401: error_response, 404: error_response, 422: error_response},
713
- )
714
- @handle_exceptions
715
- def list_workspace_run_templates(
716
- workspace_name_or_id: Union[str, UUID],
717
- filter_model: RunTemplateFilter = Depends(
718
- make_dependable(RunTemplateFilter)
719
- ),
720
- hydrate: bool = False,
721
- _: AuthContext = Security(authorize),
722
- ) -> Page[RunTemplateResponse]:
723
- """Get a page of run templates.
724
-
725
- Args:
726
- workspace_name_or_id: Name or ID of the workspace.
727
- filter_model: Filter model used for pagination, sorting,
728
- filtering.
729
- hydrate: Flag deciding whether to hydrate the output model(s)
730
- by including metadata fields in the response.
731
-
732
- Returns:
733
- Page of run templates.
734
- """
735
- workspace = zen_store().get_workspace(workspace_name_or_id)
736
- filter_model.set_scope_workspace(workspace.id)
737
-
738
- return verify_permissions_and_list_entities(
739
- filter_model=filter_model,
740
- resource_type=ResourceType.RUN_TEMPLATE,
741
- list_method=zen_store().list_run_templates,
742
- hydrate=hydrate,
743
- )
744
-
745
-
746
- @router.post(
747
- WORKSPACES + "/{workspace_name_or_id}" + RUN_TEMPLATES,
748
- responses={401: error_response, 409: error_response, 422: error_response},
749
- )
750
- @handle_exceptions
751
- def create_run_template(
752
- workspace_name_or_id: Union[str, UUID],
753
- run_template: RunTemplateRequest,
754
- _: AuthContext = Security(authorize),
755
- ) -> RunTemplateResponse:
756
- """Create a run template.
757
-
758
- Args:
759
- workspace_name_or_id: Name or ID of the workspace.
760
- run_template: Run template to create.
761
-
762
- Returns:
763
- The created run template.
764
-
765
- Raises:
766
- IllegalOperationError: If the workspace specified in the
767
- run template does not match the current workspace.
768
- """
769
- workspace = zen_store().get_workspace(workspace_name_or_id)
770
-
771
- if run_template.workspace != workspace.id:
772
- raise IllegalOperationError(
773
- "Creating run templates outside of the workspace scope "
774
- f"of this endpoint `{workspace_name_or_id}` is "
775
- f"not supported."
776
- )
777
-
778
- return verify_permissions_and_create_entity(
779
- request_model=run_template,
780
- resource_type=ResourceType.RUN_TEMPLATE,
781
- create_method=zen_store().create_run_template,
782
- )
783
-
784
-
785
- @router.get(
786
- WORKSPACES + "/{workspace_name_or_id}" + RUNS,
787
- response_model=Page[PipelineRunResponse],
788
- responses={401: error_response, 404: error_response, 422: error_response},
789
- )
790
- @handle_exceptions
791
- def list_runs(
792
- workspace_name_or_id: Union[str, UUID],
793
- runs_filter_model: PipelineRunFilter = Depends(
794
- make_dependable(PipelineRunFilter)
795
- ),
796
- hydrate: bool = False,
797
- _: AuthContext = Security(authorize),
798
- ) -> Page[PipelineRunResponse]:
799
- """Get pipeline runs according to query filters.
800
-
801
- Args:
802
- workspace_name_or_id: Name or ID of the workspace.
803
- runs_filter_model: Filter model used for pagination, sorting,
804
- filtering.
805
- hydrate: Flag deciding whether to hydrate the output model(s)
806
- by including metadata fields in the response.
807
-
808
- Returns:
809
- The pipeline runs according to query filters.
810
- """
811
- workspace = zen_store().get_workspace(workspace_name_or_id)
812
- runs_filter_model.set_scope_workspace(workspace.id)
813
-
814
- return verify_permissions_and_list_entities(
815
- filter_model=runs_filter_model,
816
- resource_type=ResourceType.PIPELINE_RUN,
817
- list_method=zen_store().list_runs,
818
- hydrate=hydrate,
819
- )
820
-
821
-
822
- @router.post(
823
- WORKSPACES + "/{workspace_name_or_id}" + SCHEDULES,
824
- response_model=ScheduleResponse,
825
- responses={401: error_response, 409: error_response, 422: error_response},
826
- )
827
- @handle_exceptions
828
- def create_schedule(
829
- workspace_name_or_id: Union[str, UUID],
830
- schedule: ScheduleRequest,
831
- auth_context: AuthContext = Security(authorize),
832
- ) -> ScheduleResponse:
833
- """Creates a schedule.
834
-
835
- Args:
836
- workspace_name_or_id: Name or ID of the workspace.
837
- schedule: Schedule to create.
838
- auth_context: Authentication context.
839
-
840
- Returns:
841
- The created schedule.
842
-
843
- Raises:
844
- IllegalOperationError: If the workspace or user specified in the
845
- schedule does not match the current workspace or authenticated user.
846
- """
847
- workspace = zen_store().get_workspace(workspace_name_or_id)
848
-
849
- if schedule.workspace != workspace.id:
850
- raise IllegalOperationError(
851
- "Creating pipeline runs outside of the workspace scope "
852
- f"of this endpoint `{workspace_name_or_id}` is "
853
- f"not supported."
854
- )
855
- if schedule.user != auth_context.user.id:
856
- raise IllegalOperationError(
857
- "Creating pipeline runs for a user other than yourself "
858
- "is not supported."
859
- )
860
- return zen_store().create_schedule(schedule=schedule)
861
-
862
-
863
- @router.post(
864
- WORKSPACES + "/{workspace_name_or_id}" + RUNS,
865
- response_model=PipelineRunResponse,
866
- responses={401: error_response, 409: error_response, 422: error_response},
867
- )
868
- @handle_exceptions
869
- def create_pipeline_run(
870
- workspace_name_or_id: Union[str, UUID],
871
- pipeline_run: PipelineRunRequest,
872
- _: AuthContext = Security(authorize),
873
- ) -> PipelineRunResponse:
874
- """Creates a pipeline run.
875
-
876
- Args:
877
- workspace_name_or_id: Name or ID of the workspace.
878
- pipeline_run: Pipeline run to create.
879
-
880
- Returns:
881
- The created pipeline run.
882
-
883
- Raises:
884
- IllegalOperationError: If the workspace specified in the
885
- pipeline run does not match the current workspace.
886
- """
887
- workspace = zen_store().get_workspace(workspace_name_or_id)
888
-
889
- if pipeline_run.workspace != workspace.id:
890
- raise IllegalOperationError(
891
- "Creating pipeline runs outside of the workspace scope "
892
- f"of this endpoint `{workspace_name_or_id}` is "
893
- f"not supported."
894
- )
895
-
896
- return verify_permissions_and_create_entity(
897
- request_model=pipeline_run,
898
- resource_type=ResourceType.PIPELINE_RUN,
899
- create_method=zen_store().create_run,
900
- )
901
-
902
-
903
- @router.post(
904
- WORKSPACES + "/{workspace_name_or_id}" + RUNS + GET_OR_CREATE,
905
- response_model=Tuple[PipelineRunResponse, bool],
906
- responses={401: error_response, 409: error_response, 422: error_response},
907
- )
908
- @handle_exceptions
909
- def get_or_create_pipeline_run(
910
- workspace_name_or_id: Union[str, UUID],
911
- pipeline_run: PipelineRunRequest,
912
- auth_context: AuthContext = Security(authorize),
913
- ) -> Tuple[PipelineRunResponse, bool]:
914
- """Get or create a pipeline run.
915
-
916
- Args:
917
- workspace_name_or_id: Name or ID of the workspace.
918
- pipeline_run: Pipeline run to create.
919
- auth_context: Authentication context.
920
-
921
- Returns:
922
- The pipeline run and a boolean indicating whether the run was created
923
- or not.
924
-
925
- Raises:
926
- IllegalOperationError: If the workspace or user specified in the
927
- pipeline run does not match the current workspace or authenticated
928
- user.
929
- """
930
- workspace = zen_store().get_workspace(workspace_name_or_id)
931
- if pipeline_run.workspace != workspace.id:
932
- raise IllegalOperationError(
933
- "Creating pipeline runs outside of the workspace scope "
934
- f"of this endpoint `{workspace_name_or_id}` is "
935
- f"not supported."
936
- )
937
- if pipeline_run.user != auth_context.user.id:
938
- raise IllegalOperationError(
939
- "Creating pipeline runs for a user other than yourself "
940
- "is not supported."
941
- )
942
-
943
- def _pre_creation_hook() -> None:
944
- verify_permission(
945
- resource_type=ResourceType.PIPELINE_RUN, action=Action.CREATE
946
- )
947
- check_entitlement(resource_type=ResourceType.PIPELINE_RUN)
948
-
949
- run, created = zen_store().get_or_create_run(
950
- pipeline_run=pipeline_run, pre_creation_hook=_pre_creation_hook
951
- )
952
- if created:
953
- report_usage(
954
- resource_type=ResourceType.PIPELINE_RUN, resource_id=run.id
955
- )
956
- else:
957
- verify_permission_for_model(run, action=Action.READ)
958
-
959
- return run, created
960
-
961
-
962
- @router.post(
963
- WORKSPACES + "/{workspace_name_or_id}" + RUN_METADATA,
964
- responses={401: error_response, 409: error_response, 422: error_response},
965
- )
966
- @handle_exceptions
967
- def create_run_metadata(
968
- workspace_name_or_id: Union[str, UUID],
969
- run_metadata: RunMetadataRequest,
970
- auth_context: AuthContext = Security(authorize),
971
- ) -> None:
972
- """Creates run metadata.
973
-
974
- Args:
975
- workspace_name_or_id: Name or ID of the workspace.
976
- run_metadata: The run metadata to create.
977
- auth_context: Authentication context.
978
-
979
- Returns:
980
- The created run metadata.
981
-
982
- Raises:
983
- IllegalOperationError: If the workspace or user specified in the run
984
- metadata does not match the current workspace or authenticated user.
985
- RuntimeError: If the resource type is not supported.
986
- """
987
- workspace = zen_store().get_workspace(run_metadata.workspace)
988
-
989
- if run_metadata.workspace != workspace.id:
990
- raise IllegalOperationError(
991
- "Creating run metadata outside of the workspace scope "
992
- f"of this endpoint `{workspace_name_or_id}` is "
993
- f"not supported."
994
- )
995
-
996
- if run_metadata.user != auth_context.user.id:
997
- raise IllegalOperationError(
998
- "Creating run metadata for a user other than yourself "
999
- "is not supported."
1000
- )
1001
-
1002
- verify_models: List[Any] = []
1003
- for resource in run_metadata.resources:
1004
- if resource.type == MetadataResourceTypes.PIPELINE_RUN:
1005
- verify_models.append(zen_store().get_run(resource.id))
1006
- elif resource.type == MetadataResourceTypes.STEP_RUN:
1007
- verify_models.append(zen_store().get_run_step(resource.id))
1008
- elif resource.type == MetadataResourceTypes.ARTIFACT_VERSION:
1009
- verify_models.append(zen_store().get_artifact_version(resource.id))
1010
- elif resource.type == MetadataResourceTypes.MODEL_VERSION:
1011
- verify_models.append(zen_store().get_model_version(resource.id))
1012
- elif resource.type == MetadataResourceTypes.SCHEDULE:
1013
- verify_models.append(zen_store().get_schedule(resource.id))
1014
- else:
1015
- raise RuntimeError(f"Unknown resource type: {resource.type}")
1016
-
1017
- batch_verify_permissions_for_models(
1018
- models=verify_models,
1019
- action=Action.UPDATE,
1020
- )
1021
-
1022
- verify_permission(
1023
- resource_type=ResourceType.RUN_METADATA, action=Action.CREATE
1024
- )
1025
-
1026
- zen_store().create_run_metadata(run_metadata)
1027
- return None
1028
-
1029
-
1030
- @router.post(
1031
- WORKSPACES + "/{workspace_name_or_id}" + SECRETS,
1032
- response_model=SecretResponse,
1033
- responses={401: error_response, 409: error_response, 422: error_response},
1034
- )
1035
- @handle_exceptions
1036
- def create_secret(
1037
- workspace_name_or_id: Union[str, UUID],
1038
- secret: SecretRequest,
1039
- _: AuthContext = Security(authorize),
1040
- ) -> SecretResponse:
1041
- """Creates a secret.
1042
-
1043
- Args:
1044
- workspace_name_or_id: Name or ID of the workspace.
1045
- secret: Secret to create.
1046
-
1047
- Returns:
1048
- The created secret.
1049
-
1050
- Raises:
1051
- IllegalOperationError: If the workspace specified in the
1052
- secret does not match the current workspace.
1053
- """
1054
- workspace = zen_store().get_workspace(workspace_name_or_id)
1055
-
1056
- if secret.workspace != workspace.id:
1057
- raise IllegalOperationError(
1058
- "Creating a secret outside of the workspace scope "
1059
- f"of this endpoint `{workspace_name_or_id}` is "
1060
- f"not supported."
1061
- )
1062
-
1063
- return verify_permissions_and_create_entity(
1064
- request_model=secret,
1065
- resource_type=ResourceType.SECRET,
1066
- create_method=zen_store().create_secret,
1067
- )
1068
-
1069
-
1070
- @router.get(
1071
- WORKSPACES + "/{workspace_name_or_id}" + CODE_REPOSITORIES,
1072
- response_model=Page[CodeRepositoryResponse],
1073
- responses={401: error_response, 404: error_response, 422: error_response},
1074
- )
1075
- @handle_exceptions
1076
- def list_workspace_code_repositories(
1077
- workspace_name_or_id: Union[str, UUID],
1078
- filter_model: CodeRepositoryFilter = Depends(
1079
- make_dependable(CodeRepositoryFilter)
1080
- ),
1081
- hydrate: bool = False,
1082
- _: AuthContext = Security(authorize),
1083
- ) -> Page[CodeRepositoryResponse]:
1084
- """Gets code repositories defined for a specific workspace.
1085
-
1086
- # noqa: DAR401
1087
-
1088
- Args:
1089
- workspace_name_or_id: Name or ID of the workspace.
1090
- filter_model: Filter model used for pagination, sorting,
1091
- filtering.
1092
- hydrate: Flag deciding whether to hydrate the output model(s)
1093
- by including metadata fields in the response.
1094
-
1095
- Returns:
1096
- All code repositories within the workspace.
1097
- """
1098
- workspace = zen_store().get_workspace(workspace_name_or_id)
1099
- filter_model.set_scope_workspace(workspace.id)
1100
-
1101
- return verify_permissions_and_list_entities(
1102
- filter_model=filter_model,
1103
- resource_type=ResourceType.CODE_REPOSITORY,
1104
- list_method=zen_store().list_code_repositories,
1105
- hydrate=hydrate,
1106
- )
1107
-
1108
-
1109
- @router.post(
1110
- WORKSPACES + "/{workspace_name_or_id}" + CODE_REPOSITORIES,
1111
- response_model=CodeRepositoryResponse,
1112
- responses={401: error_response, 409: error_response, 422: error_response},
1113
- )
1114
- @handle_exceptions
1115
- def create_code_repository(
1116
- workspace_name_or_id: Union[str, UUID],
1117
- code_repository: CodeRepositoryRequest,
1118
- _: AuthContext = Security(authorize),
1119
- ) -> CodeRepositoryResponse:
1120
- """Creates a code repository.
1121
-
1122
- Args:
1123
- workspace_name_or_id: Name or ID of the workspace.
1124
- code_repository: Code repository to create.
1125
-
1126
- Returns:
1127
- The created code repository.
1128
-
1129
- Raises:
1130
- IllegalOperationError: If the workspace or user specified in the
1131
- code repository does not match the current workspace or
1132
- authenticated user.
1133
- """
1134
- workspace = zen_store().get_workspace(workspace_name_or_id)
1135
-
1136
- if code_repository.workspace != workspace.id:
1137
- raise IllegalOperationError(
1138
- "Creating code repositories outside of the workspace scope "
1139
- f"of this endpoint `{workspace_name_or_id}` is "
1140
- f"not supported."
1141
- )
1142
-
1143
- return verify_permissions_and_create_entity(
1144
- request_model=code_repository,
1145
- resource_type=ResourceType.CODE_REPOSITORY,
1146
- create_method=zen_store().create_code_repository,
1147
- )
1148
-
1149
-
1150
- @router.get(
1151
- WORKSPACES + "/{workspace_name_or_id}" + STATISTICS,
1152
- response_model=Dict[str, int],
1153
- responses={401: error_response, 404: error_response, 422: error_response},
1154
- )
1155
- @handle_exceptions
1156
- def get_workspace_statistics(
1157
- workspace_name_or_id: Union[str, UUID],
1158
- auth_context: AuthContext = Security(authorize),
1159
- ) -> Dict[str, int]:
1160
- """Gets statistics of a workspace.
1161
-
1162
- # noqa: DAR401
1163
-
1164
- Args:
1165
- workspace_name_or_id: Name or ID of the workspace to get statistics for.
1166
- auth_context: Authentication context.
1167
-
1168
- Returns:
1169
- All pipelines within the workspace.
1170
- """
1171
- workspace = zen_store().get_workspace(workspace_name_or_id)
1172
-
1173
- user_id = auth_context.user.id
1174
- component_filter = ComponentFilter(workspace_id=workspace.id)
1175
- component_filter.configure_rbac(
1176
- authenticated_user_id=user_id,
1177
- id=get_allowed_resource_ids(
1178
- resource_type=ResourceType.STACK_COMPONENT
1179
- ),
1180
- )
1181
-
1182
- stack_filter = StackFilter(workspace_id=workspace.id)
1183
- stack_filter.configure_rbac(
1184
- authenticated_user_id=user_id,
1185
- id=get_allowed_resource_ids(resource_type=ResourceType.STACK),
1186
- )
1187
-
1188
- run_filter = PipelineRunFilter(workspace_id=workspace.id)
1189
- run_filter.configure_rbac(
1190
- authenticated_user_id=user_id,
1191
- id=get_allowed_resource_ids(resource_type=ResourceType.PIPELINE_RUN),
1192
- )
1193
-
1194
- pipeline_filter = PipelineFilter(workspace_id=workspace.id)
1195
- pipeline_filter.configure_rbac(
1196
- authenticated_user_id=user_id,
1197
- id=get_allowed_resource_ids(resource_type=ResourceType.PIPELINE),
1198
- )
1199
-
1200
- return {
1201
- "stacks": zen_store().count_stacks(filter_model=stack_filter),
1202
- "components": zen_store().count_stack_components(
1203
- filter_model=component_filter
1204
- ),
1205
- "pipelines": zen_store().count_pipelines(filter_model=pipeline_filter),
1206
- "runs": zen_store().count_runs(filter_model=run_filter),
1207
- }
1208
-
1209
-
1210
- @router.get(
1211
- WORKSPACES + "/{workspace_name_or_id}" + SERVICE_CONNECTORS,
1212
- response_model=Page[ServiceConnectorResponse],
1213
- responses={401: error_response, 404: error_response, 422: error_response},
1214
- )
1215
- @handle_exceptions
1216
- def list_workspace_service_connectors(
1217
- workspace_name_or_id: Union[str, UUID],
1218
- connector_filter_model: ServiceConnectorFilter = Depends(
1219
- make_dependable(ServiceConnectorFilter)
1220
- ),
1221
- hydrate: bool = False,
1222
- _: AuthContext = Security(authorize),
1223
- ) -> Page[ServiceConnectorResponse]:
1224
- """List service connectors that are part of a specific workspace.
1225
-
1226
- # noqa: DAR401
1227
-
1228
- Args:
1229
- workspace_name_or_id: Name or ID of the workspace.
1230
- connector_filter_model: Filter model used for pagination, sorting,
1231
- filtering.
1232
- hydrate: Flag deciding whether to hydrate the output model(s)
1233
- by including metadata fields in the response.
1234
-
1235
- Returns:
1236
- All service connectors part of the specified workspace.
1237
- """
1238
- workspace = zen_store().get_workspace(workspace_name_or_id)
1239
- connector_filter_model.set_scope_workspace(workspace.id)
1240
-
1241
- return verify_permissions_and_list_entities(
1242
- filter_model=connector_filter_model,
1243
- resource_type=ResourceType.SERVICE_CONNECTOR,
1244
- list_method=zen_store().list_service_connectors,
1245
- hydrate=hydrate,
1246
- )
1247
-
1248
-
1249
- @router.post(
1250
- WORKSPACES + "/{workspace_name_or_id}" + SERVICE_CONNECTORS,
1251
- response_model=ServiceConnectorResponse,
1252
- responses={401: error_response, 409: error_response, 422: error_response},
1253
- )
1254
- @handle_exceptions
1255
- def create_service_connector(
1256
- workspace_name_or_id: Union[str, UUID],
1257
- connector: ServiceConnectorRequest,
1258
- _: AuthContext = Security(authorize),
1259
- ) -> ServiceConnectorResponse:
1260
- """Creates a service connector.
1261
-
1262
- Args:
1263
- workspace_name_or_id: Name or ID of the workspace.
1264
- connector: Service connector to register.
1265
-
1266
- Returns:
1267
- The created service connector.
1268
-
1269
- Raises:
1270
- IllegalOperationError: If the workspace or user specified in the service
1271
- connector does not match the current workspace or authenticated
1272
- user.
1273
- """
1274
- workspace = zen_store().get_workspace(workspace_name_or_id)
1275
-
1276
- if connector.workspace != workspace.id:
1277
- raise IllegalOperationError(
1278
- "Creating connectors outside of the workspace scope "
1279
- f"of this endpoint `{workspace_name_or_id}` is "
1280
- f"not supported."
1281
- )
1282
-
1283
- return verify_permissions_and_create_entity(
1284
- request_model=connector,
1285
- resource_type=ResourceType.SERVICE_CONNECTOR,
1286
- create_method=zen_store().create_service_connector,
1287
- )
1288
-
1289
-
1290
- @router.get(
1291
- WORKSPACES
1292
- + "/{workspace_name_or_id}"
1293
- + SERVICE_CONNECTORS
1294
- + SERVICE_CONNECTOR_RESOURCES,
1295
- response_model=List[ServiceConnectorResourcesModel],
1296
- responses={401: error_response, 404: error_response, 422: error_response},
1297
- )
1298
- @handle_exceptions
1299
- def list_service_connector_resources(
1300
- workspace_name_or_id: Union[str, UUID],
1301
- connector_type: Optional[str] = None,
1302
- resource_type: Optional[str] = None,
1303
- resource_id: Optional[str] = None,
1304
- auth_context: AuthContext = Security(authorize),
1305
- ) -> List[ServiceConnectorResourcesModel]:
1306
- """List resources that can be accessed by service connectors.
1307
-
1308
- Args:
1309
- workspace_name_or_id: Name or ID of the workspace.
1310
- connector_type: the service connector type identifier to filter by.
1311
- resource_type: the resource type identifier to filter by.
1312
- resource_id: the resource identifier to filter by.
1313
- auth_context: Authentication context.
1314
-
1315
- Returns:
1316
- The matching list of resources that available service
1317
- connectors have access to.
1318
- """
1319
- workspace = zen_store().get_workspace(workspace_name_or_id)
1320
-
1321
- filter_model = ServiceConnectorFilter(
1322
- connector_type=connector_type,
1323
- resource_type=resource_type,
1324
- )
1325
- filter_model.set_scope_workspace(workspace.id)
1326
-
1327
- allowed_ids = get_allowed_resource_ids(
1328
- resource_type=ResourceType.SERVICE_CONNECTOR
1329
- )
1330
- filter_model.configure_rbac(
1331
- authenticated_user_id=auth_context.user.id, id=allowed_ids
1332
- )
1333
-
1334
- return zen_store().list_service_connector_resources(
1335
- workspace_name_or_id=workspace_name_or_id,
1336
- connector_type=connector_type,
1337
- resource_type=resource_type,
1338
- resource_id=resource_id,
1339
- filter_model=filter_model,
1340
- )
1341
-
1342
-
1343
- @router.post(
1344
- WORKSPACES + "/{workspace_name_or_id}" + MODELS,
1345
- response_model=ModelResponse,
1346
- responses={401: error_response, 409: error_response, 422: error_response},
1347
- )
1348
- @handle_exceptions
1349
- def create_model(
1350
- workspace_name_or_id: Union[str, UUID],
1351
- model: ModelRequest,
1352
- _: AuthContext = Security(authorize),
1353
- ) -> ModelResponse:
1354
- """Create a new model.
1355
-
1356
- Args:
1357
- workspace_name_or_id: Name or ID of the workspace.
1358
- model: The model to create.
1359
-
1360
- Returns:
1361
- The created model.
1362
-
1363
- Raises:
1364
- IllegalOperationError: If the workspace or user specified in the
1365
- model does not match the current workspace or authenticated
1366
- user.
1367
- """
1368
- workspace = zen_store().get_workspace(workspace_name_or_id)
1369
-
1370
- if model.workspace != workspace.id:
1371
- raise IllegalOperationError(
1372
- "Creating models outside of the workspace scope "
1373
- f"of this endpoint `{workspace_name_or_id}` is "
1374
- f"not supported."
1375
- )
1376
-
1377
- return verify_permissions_and_create_entity(
1378
- request_model=model,
1379
- resource_type=ResourceType.MODEL,
1380
- create_method=zen_store().create_model,
1381
- )
1382
-
1383
-
1384
- @router.post(
1385
- WORKSPACES
1386
- + "/{workspace_name_or_id}"
1387
- + MODELS
1388
- + "/{model_name_or_id}"
1389
- + MODEL_VERSIONS,
1390
- response_model=ModelVersionResponse,
1391
- responses={401: error_response, 409: error_response, 422: error_response},
1392
- )
1393
- @handle_exceptions
1394
- def create_model_version(
1395
- workspace_name_or_id: Union[str, UUID],
1396
- model_name_or_id: Union[str, UUID],
1397
- model_version: ModelVersionRequest,
1398
- auth_context: AuthContext = Security(authorize),
1399
- ) -> ModelVersionResponse:
1400
- """Create a new model version.
1401
-
1402
- Args:
1403
- model_name_or_id: Name or ID of the model.
1404
- workspace_name_or_id: Name or ID of the workspace.
1405
- model_version: The model version to create.
1406
- auth_context: Authentication context.
1407
-
1408
- Returns:
1409
- The created model version.
1410
-
1411
- Raises:
1412
- IllegalOperationError: If the workspace specified in the
1413
- model version does not match the current workspace.
1414
- """
1415
- workspace = zen_store().get_workspace(workspace_name_or_id)
1416
-
1417
- if model_version.workspace != workspace.id:
1418
- raise IllegalOperationError(
1419
- "Creating model versions outside of the workspace scope "
1420
- f"of this endpoint `{workspace_name_or_id}` is "
1421
- f"not supported."
1422
- )
1423
-
1424
- return verify_permissions_and_create_entity(
1425
- request_model=model_version,
1426
- resource_type=ResourceType.MODEL_VERSION,
1427
- create_method=zen_store().create_model_version,
1428
- )
1429
-
1430
-
1431
- @router.post(
1432
- WORKSPACES + "/{workspace_name_or_id}" + SERVICES,
1433
- response_model=ServiceResponse,
1434
- responses={401: error_response, 409: error_response, 422: error_response},
1435
- )
1436
- @handle_exceptions
1437
- def create_service(
1438
- workspace_name_or_id: Union[str, UUID],
1439
- service: ServiceRequest,
1440
- _: AuthContext = Security(authorize),
1441
- ) -> ServiceResponse:
1442
- """Create a new service.
1443
-
1444
- Args:
1445
- workspace_name_or_id: Name or ID of the workspace.
1446
- service: The service to create.
1447
-
1448
- Returns:
1449
- The created service.
1450
-
1451
- Raises:
1452
- IllegalOperationError: If the workspace or user specified in the
1453
- model does not match the current workspace or authenticated
1454
- user.
1455
- """
1456
- workspace = zen_store().get_workspace(workspace_name_or_id)
1457
-
1458
- if service.workspace != workspace.id:
1459
- raise IllegalOperationError(
1460
- "Creating models outside of the workspace scope "
1461
- f"of this endpoint `{workspace_name_or_id}` is "
1462
- f"not supported."
1463
- )
1464
-
1465
- return verify_permissions_and_create_entity(
1466
- request_model=service,
1467
- resource_type=ResourceType.SERVICE,
1468
- create_method=zen_store().create_service,
1469
- )