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
@@ -13,6 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Endpoint definitions for services."""
15
15
 
16
+ from typing import Optional, Union
16
17
  from uuid import UUID
17
18
 
18
19
  from fastapi import APIRouter, Depends, Security
@@ -35,6 +36,7 @@ from zenml.zen_server.rbac.endpoint_utils import (
35
36
  verify_permissions_and_update_entity,
36
37
  )
37
38
  from zenml.zen_server.rbac.models import ResourceType
39
+ from zenml.zen_server.routers.projects_endpoints import workspace_router
38
40
  from zenml.zen_server.utils import (
39
41
  handle_exceptions,
40
42
  make_dependable,
@@ -50,32 +52,43 @@ router = APIRouter(
50
52
 
51
53
  @router.post(
52
54
  "",
53
- response_model=ServiceResponse,
54
55
  responses={401: error_response, 422: error_response},
55
56
  )
57
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
58
+ # and can be removed after the migration
59
+ @workspace_router.post(
60
+ "/{project_name_or_id}" + SERVICES,
61
+ responses={401: error_response, 409: error_response, 422: error_response},
62
+ deprecated=True,
63
+ tags=["services"],
64
+ )
56
65
  @handle_exceptions
57
66
  def create_service(
58
67
  service: ServiceRequest,
68
+ project_name_or_id: Optional[Union[str, UUID]] = None,
59
69
  _: AuthContext = Security(authorize),
60
70
  ) -> ServiceResponse:
61
71
  """Creates a new service.
62
72
 
63
73
  Args:
64
- service: The model containing the attributes of the new service.
74
+ service: The service to create.
75
+ project_name_or_id: Optional name or ID of the project.
65
76
 
66
77
  Returns:
67
- The created service object.
78
+ The created service.
68
79
  """
80
+ if project_name_or_id:
81
+ project = zen_store().get_project(project_name_or_id)
82
+ service.project = project.id
83
+
69
84
  return verify_permissions_and_create_entity(
70
85
  request_model=service,
71
86
  create_method=zen_store().create_service,
72
- resource_type=ResourceType.SERVICE,
73
87
  )
74
88
 
75
89
 
76
90
  @router.get(
77
91
  "",
78
- response_model=Page[ServiceResponse],
79
92
  responses={401: error_response, 404: error_response, 422: error_response},
80
93
  )
81
94
  @handle_exceptions
@@ -105,7 +118,6 @@ def list_services(
105
118
 
106
119
  @router.get(
107
120
  "/{service_id}",
108
- response_model=ServiceResponse,
109
121
  responses={401: error_response, 404: error_response, 422: error_response},
110
122
  )
111
123
  @handle_exceptions
@@ -133,7 +145,6 @@ def get_service(
133
145
 
134
146
  @router.put(
135
147
  "/{service_id}",
136
- response_model=ServiceResponse,
137
148
  responses={401: error_response, 404: error_response, 422: error_response},
138
149
  )
139
150
  @handle_exceptions
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Endpoint definitions for stack components."""
15
15
 
16
- from typing import List
16
+ from typing import List, Optional, Union
17
17
  from uuid import UUID
18
18
 
19
19
  from fastapi import APIRouter, Depends, Security
@@ -22,6 +22,7 @@ from zenml.constants import API, COMPONENT_TYPES, STACK_COMPONENTS, VERSION_1
22
22
  from zenml.enums import StackComponentType
23
23
  from zenml.models import (
24
24
  ComponentFilter,
25
+ ComponentRequest,
25
26
  ComponentResponse,
26
27
  ComponentUpdate,
27
28
  Page,
@@ -29,6 +30,7 @@ from zenml.models import (
29
30
  from zenml.zen_server.auth import AuthContext, authorize
30
31
  from zenml.zen_server.exceptions import error_response
31
32
  from zenml.zen_server.rbac.endpoint_utils import (
33
+ verify_permissions_and_create_entity,
32
34
  verify_permissions_and_delete_entity,
33
35
  verify_permissions_and_get_entity,
34
36
  verify_permissions_and_list_entities,
@@ -36,6 +38,7 @@ from zenml.zen_server.rbac.endpoint_utils import (
36
38
  )
37
39
  from zenml.zen_server.rbac.models import Action, ResourceType
38
40
  from zenml.zen_server.rbac.utils import verify_permission_for_model
41
+ from zenml.zen_server.routers.projects_endpoints import workspace_router
39
42
  from zenml.zen_server.utils import (
40
43
  handle_exceptions,
41
44
  make_dependable,
@@ -55,29 +58,88 @@ types_router = APIRouter(
55
58
  )
56
59
 
57
60
 
61
+ @router.post(
62
+ "",
63
+ responses={401: error_response, 409: error_response, 422: error_response},
64
+ )
65
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
66
+ # and can be removed after the migration
67
+ @workspace_router.post(
68
+ "/{project_name_or_id}" + STACK_COMPONENTS,
69
+ responses={401: error_response, 409: error_response, 422: error_response},
70
+ deprecated=True,
71
+ tags=["stack_components"],
72
+ )
73
+ @handle_exceptions
74
+ def create_stack_component(
75
+ component: ComponentRequest,
76
+ project_name_or_id: Optional[Union[str, UUID]] = None,
77
+ _: AuthContext = Security(authorize),
78
+ ) -> ComponentResponse:
79
+ """Creates a stack component.
80
+
81
+ Args:
82
+ component: Stack component to register.
83
+ project_name_or_id: Optional name or ID of the project.
84
+
85
+ Returns:
86
+ The created stack component.
87
+ """
88
+ if component.connector:
89
+ service_connector = zen_store().get_service_connector(
90
+ component.connector
91
+ )
92
+ verify_permission_for_model(service_connector, action=Action.READ)
93
+
94
+ from zenml.stack.utils import validate_stack_component_config
95
+
96
+ validate_stack_component_config(
97
+ configuration_dict=component.configuration,
98
+ flavor=component.flavor,
99
+ component_type=component.type,
100
+ zen_store=zen_store(),
101
+ # We allow custom flavors to fail import on the server side.
102
+ validate_custom_flavors=False,
103
+ )
104
+
105
+ return verify_permissions_and_create_entity(
106
+ request_model=component,
107
+ create_method=zen_store().create_stack_component,
108
+ )
109
+
110
+
58
111
  @router.get(
59
112
  "",
60
- response_model=Page[ComponentResponse],
61
113
  responses={401: error_response, 404: error_response, 422: error_response},
62
114
  )
115
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
116
+ # and can be removed after the migration
117
+ @workspace_router.get(
118
+ "/{project_name_or_id}" + STACK_COMPONENTS,
119
+ responses={401: error_response, 404: error_response, 422: error_response},
120
+ deprecated=True,
121
+ tags=["stack_components"],
122
+ )
63
123
  @handle_exceptions
64
124
  def list_stack_components(
65
125
  component_filter_model: ComponentFilter = Depends(
66
126
  make_dependable(ComponentFilter)
67
127
  ),
128
+ project_name_or_id: Optional[Union[str, UUID]] = None,
68
129
  hydrate: bool = False,
69
130
  _: AuthContext = Security(authorize),
70
131
  ) -> Page[ComponentResponse]:
71
- """Get a list of all stack components for a specific type.
132
+ """Get a list of all stack components.
72
133
 
73
134
  Args:
74
135
  component_filter_model: Filter model used for pagination, sorting,
75
136
  filtering.
137
+ project_name_or_id: Optional name or ID of the project to filter by.
76
138
  hydrate: Flag deciding whether to hydrate the output model(s)
77
139
  by including metadata fields in the response.
78
140
 
79
141
  Returns:
80
- List of stack components for a specific type.
142
+ List of stack components matching the filter criteria.
81
143
  """
82
144
  return verify_permissions_and_list_entities(
83
145
  filter_model=component_filter_model,
@@ -89,7 +151,6 @@ def list_stack_components(
89
151
 
90
152
  @router.get(
91
153
  "/{component_id}",
92
- response_model=ComponentResponse,
93
154
  responses={401: error_response, 404: error_response, 422: error_response},
94
155
  )
95
156
  @handle_exceptions
@@ -117,7 +178,6 @@ def get_stack_component(
117
178
 
118
179
  @router.put(
119
180
  "/{component_id}",
120
- response_model=ComponentResponse,
121
181
  responses={401: error_response, 404: error_response, 422: error_response},
122
182
  )
123
183
  @handle_exceptions
@@ -185,7 +245,6 @@ def deregister_stack_component(
185
245
 
186
246
  @types_router.get(
187
247
  "",
188
- response_model=List[str],
189
248
  responses={401: error_response, 404: error_response, 422: error_response},
190
249
  )
191
250
  @handle_exceptions
@@ -13,12 +13,19 @@
13
13
  # permissions and limitations under the License.
14
14
  """Endpoint definitions for stacks."""
15
15
 
16
+ from typing import Optional, Union
16
17
  from uuid import UUID
17
18
 
18
19
  from fastapi import APIRouter, Depends, Security
19
20
 
20
21
  from zenml.constants import API, STACKS, VERSION_1
21
- from zenml.models import Page, StackFilter, StackResponse, StackUpdate
22
+ from zenml.models import (
23
+ Page,
24
+ StackFilter,
25
+ StackRequest,
26
+ StackResponse,
27
+ StackUpdate,
28
+ )
22
29
  from zenml.zen_server.auth import AuthContext, authorize
23
30
  from zenml.zen_server.exceptions import error_response
24
31
  from zenml.zen_server.rbac.endpoint_utils import (
@@ -28,7 +35,12 @@ from zenml.zen_server.rbac.endpoint_utils import (
28
35
  verify_permissions_and_update_entity,
29
36
  )
30
37
  from zenml.zen_server.rbac.models import Action, ResourceType
31
- from zenml.zen_server.rbac.utils import batch_verify_permissions_for_models
38
+ from zenml.zen_server.rbac.utils import (
39
+ batch_verify_permissions_for_models,
40
+ verify_permission,
41
+ verify_permission_for_model,
42
+ )
43
+ from zenml.zen_server.routers.projects_endpoints import workspace_router
32
44
  from zenml.zen_server.utils import (
33
45
  handle_exceptions,
34
46
  make_dependable,
@@ -42,13 +54,91 @@ router = APIRouter(
42
54
  )
43
55
 
44
56
 
57
+ @router.post(
58
+ "",
59
+ responses={401: error_response, 409: error_response, 422: error_response},
60
+ )
61
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
62
+ # and can be removed after the migration
63
+ @workspace_router.post(
64
+ "/{project_name_or_id}" + STACKS,
65
+ responses={401: error_response, 409: error_response, 422: error_response},
66
+ deprecated=True,
67
+ tags=["stacks"],
68
+ )
69
+ @handle_exceptions
70
+ def create_stack(
71
+ stack: StackRequest,
72
+ project_name_or_id: Optional[Union[str, UUID]] = None,
73
+ auth_context: AuthContext = Security(authorize),
74
+ ) -> StackResponse:
75
+ """Creates a stack.
76
+
77
+ Args:
78
+ stack: Stack to register.
79
+ project_name_or_id: Optional name or ID of the project.
80
+ auth_context: Authentication context.
81
+
82
+ Returns:
83
+ The created stack.
84
+ """
85
+ # Check the service connector creation
86
+ is_connector_create_needed = False
87
+ for connector_id_or_info in stack.service_connectors:
88
+ if isinstance(connector_id_or_info, UUID):
89
+ service_connector = zen_store().get_service_connector(
90
+ connector_id_or_info, hydrate=False
91
+ )
92
+ verify_permission_for_model(
93
+ model=service_connector, action=Action.READ
94
+ )
95
+ else:
96
+ is_connector_create_needed = True
97
+
98
+ # Check the component creation
99
+ if is_connector_create_needed:
100
+ verify_permission(
101
+ resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
102
+ )
103
+ is_component_create_needed = False
104
+ for components in stack.components.values():
105
+ for component_id_or_info in components:
106
+ if isinstance(component_id_or_info, UUID):
107
+ component = zen_store().get_stack_component(
108
+ component_id_or_info, hydrate=False
109
+ )
110
+ verify_permission_for_model(
111
+ model=component, action=Action.READ
112
+ )
113
+ else:
114
+ is_component_create_needed = True
115
+ if is_component_create_needed:
116
+ verify_permission(
117
+ resource_type=ResourceType.STACK_COMPONENT,
118
+ action=Action.CREATE,
119
+ )
120
+
121
+ # Check the stack creation
122
+ verify_permission_for_model(model=stack, action=Action.CREATE)
123
+
124
+ return zen_store().create_stack(stack)
125
+
126
+
45
127
  @router.get(
46
128
  "",
47
- response_model=Page[StackResponse],
48
129
  responses={401: error_response, 404: error_response, 422: error_response},
49
130
  )
131
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
132
+ # and can be removed after the migration
133
+ @workspace_router.get(
134
+ "/{project_name_or_id}" + STACKS,
135
+ responses={401: error_response, 404: error_response, 422: error_response},
136
+ deprecated=True,
137
+ tags=["stacks"],
138
+ )
50
139
  @handle_exceptions
51
140
  def list_stacks(
141
+ project_name_or_id: Optional[Union[str, UUID]] = None,
52
142
  stack_filter_model: StackFilter = Depends(make_dependable(StackFilter)),
53
143
  hydrate: bool = False,
54
144
  _: AuthContext = Security(authorize),
@@ -56,13 +146,14 @@ def list_stacks(
56
146
  """Returns all stacks.
57
147
 
58
148
  Args:
149
+ project_name_or_id: Optional name or ID of the project to filter by.
59
150
  stack_filter_model: Filter model used for pagination, sorting,
60
151
  filtering.
61
152
  hydrate: Flag deciding whether to hydrate the output model(s)
62
153
  by including metadata fields in the response.
63
154
 
64
155
  Returns:
65
- All stacks.
156
+ All stacks matching the filter criteria.
66
157
  """
67
158
  return verify_permissions_and_list_entities(
68
159
  filter_model=stack_filter_model,
@@ -74,7 +165,6 @@ def list_stacks(
74
165
 
75
166
  @router.get(
76
167
  "/{stack_id}",
77
- response_model=StackResponse,
78
168
  responses={401: error_response, 404: error_response, 422: error_response},
79
169
  )
80
170
  @handle_exceptions
@@ -100,7 +190,6 @@ def get_stack(
100
190
 
101
191
  @router.put(
102
192
  "/{stack_id}",
103
- response_model=StackResponse,
104
193
  responses={401: error_response, 404: error_response, 422: error_response},
105
194
  )
106
195
  @handle_exceptions
@@ -37,6 +37,9 @@ from zenml.models import (
37
37
  )
38
38
  from zenml.zen_server.auth import AuthContext, authorize
39
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
+ )
40
43
  from zenml.zen_server.rbac.models import Action, ResourceType
41
44
  from zenml.zen_server.rbac.utils import (
42
45
  dehydrate_page,
@@ -47,6 +50,7 @@ from zenml.zen_server.rbac.utils import (
47
50
  from zenml.zen_server.utils import (
48
51
  handle_exceptions,
49
52
  make_dependable,
53
+ set_filter_project_scope,
50
54
  zen_store,
51
55
  )
52
56
 
@@ -59,7 +63,6 @@ router = APIRouter(
59
63
 
60
64
  @router.get(
61
65
  "",
62
- response_model=Page[StepRunResponse],
63
66
  responses={401: error_response, 404: error_response, 422: error_response},
64
67
  )
65
68
  @handle_exceptions
@@ -82,8 +85,14 @@ def list_run_steps(
82
85
  Returns:
83
86
  The run steps according to query filters.
84
87
  """
88
+ # A project scoped request must always be scoped to a specific
89
+ # project. This is required for the RBAC check to work.
90
+ set_filter_project_scope(step_run_filter_model)
91
+ assert isinstance(step_run_filter_model.project, UUID)
92
+
85
93
  allowed_pipeline_run_ids = get_allowed_resource_ids(
86
- resource_type=ResourceType.PIPELINE_RUN
94
+ resource_type=ResourceType.PIPELINE_RUN,
95
+ project_id=step_run_filter_model.project,
87
96
  )
88
97
  step_run_filter_model.configure_rbac(
89
98
  authenticated_user_id=auth_context.user.id,
@@ -98,7 +107,6 @@ def list_run_steps(
98
107
 
99
108
  @router.post(
100
109
  "",
101
- response_model=StepRunResponse,
102
110
  responses={401: error_response, 409: error_response, 422: error_response},
103
111
  )
104
112
  @handle_exceptions
@@ -110,20 +118,22 @@ def create_run_step(
110
118
 
111
119
  Args:
112
120
  step: The run step to create.
121
+ _: Authentication context.
113
122
 
114
123
  Returns:
115
124
  The created run step.
116
125
  """
117
126
  pipeline_run = zen_store().get_run(step.pipeline_run_id)
118
- verify_permission_for_model(pipeline_run, action=Action.UPDATE)
119
127
 
120
- step_response = zen_store().create_run_step(step_run=step)
121
- return dehydrate_response_model(step_response)
128
+ return verify_permissions_and_create_entity(
129
+ request_model=step,
130
+ create_method=zen_store().create_run_step,
131
+ surrogate_models=[pipeline_run],
132
+ )
122
133
 
123
134
 
124
135
  @router.get(
125
136
  "/{step_id}",
126
- response_model=StepRunResponse,
127
137
  responses={401: error_response, 404: error_response, 422: error_response},
128
138
  )
129
139
  @handle_exceptions
@@ -157,7 +167,6 @@ def get_step(
157
167
 
158
168
  @router.put(
159
169
  "/{step_id}",
160
- response_model=StepRunResponse,
161
170
  responses={401: error_response, 404: error_response, 422: error_response},
162
171
  )
163
172
  @handle_exceptions
@@ -187,7 +196,6 @@ def update_step(
187
196
 
188
197
  @router.get(
189
198
  "/{step_id}" + STEP_CONFIGURATION,
190
- response_model=Dict[str, Any],
191
199
  responses={401: error_response, 404: error_response, 422: error_response},
192
200
  )
193
201
  @handle_exceptions
@@ -212,7 +220,6 @@ def get_step_configuration(
212
220
 
213
221
  @router.get(
214
222
  "/{step_id}" + STATUS,
215
- response_model=ExecutionStatus,
216
223
  responses={401: error_response, 404: error_response, 422: error_response},
217
224
  )
218
225
  @handle_exceptions
@@ -237,7 +244,6 @@ def get_step_status(
237
244
 
238
245
  @router.get(
239
246
  "/{step_id}" + LOGS,
240
- response_model=str,
241
247
  responses={401: error_response, 404: error_response, 422: error_response},
242
248
  )
243
249
  @handle_exceptions
@@ -0,0 +1,115 @@
1
+ # Copyright (c) ZenML GmbH 2023. 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 the link between tags and resources."""
15
+
16
+ from typing import List
17
+
18
+ from fastapi import APIRouter, Security
19
+
20
+ from zenml.constants import (
21
+ API,
22
+ BATCH,
23
+ TAG_RESOURCES,
24
+ VERSION_1,
25
+ )
26
+ from zenml.models import TagResourceRequest, TagResourceResponse
27
+ from zenml.zen_server.auth import AuthContext, authorize
28
+ from zenml.zen_server.exceptions import error_response
29
+ from zenml.zen_server.utils import (
30
+ handle_exceptions,
31
+ zen_store,
32
+ )
33
+
34
+ router = APIRouter(
35
+ prefix=API + VERSION_1 + TAG_RESOURCES,
36
+ tags=["tag_resources"],
37
+ responses={401: error_response, 403: error_response},
38
+ )
39
+
40
+
41
+ @router.post(
42
+ "",
43
+ responses={401: error_response, 404: error_response, 422: error_response},
44
+ )
45
+ @handle_exceptions
46
+ def create_tag_resource(
47
+ tag_resource: TagResourceRequest,
48
+ _: AuthContext = Security(authorize),
49
+ ) -> TagResourceResponse:
50
+ """Attach different tags to different resources.
51
+
52
+ Args:
53
+ tag_resource: A tag resource request.
54
+
55
+ Returns:
56
+ A tag resource response.
57
+ """
58
+ return zen_store().create_tag_resource(tag_resource=tag_resource)
59
+
60
+
61
+ @router.post(
62
+ BATCH,
63
+ responses={401: error_response, 409: error_response, 422: error_response},
64
+ )
65
+ @handle_exceptions
66
+ def batch_create_tag_resource(
67
+ tag_resources: List[TagResourceRequest],
68
+ _: AuthContext = Security(authorize),
69
+ ) -> List[TagResourceResponse]:
70
+ """Attach different tags to different resources.
71
+
72
+ Args:
73
+ tag_resources: A list of tag resource requests.
74
+
75
+ Returns:
76
+ A list of tag resource responses.
77
+ """
78
+ return [
79
+ zen_store().create_tag_resource(tag_resource=tag_resource)
80
+ for tag_resource in tag_resources
81
+ ]
82
+
83
+
84
+ @router.delete(
85
+ "",
86
+ responses={401: error_response, 404: error_response, 422: error_response},
87
+ )
88
+ @handle_exceptions
89
+ def delete_tag_resource(
90
+ tag_resource: TagResourceRequest,
91
+ _: AuthContext = Security(authorize),
92
+ ) -> None:
93
+ """Detach a tag from a resource.
94
+
95
+ Args:
96
+ tag_resource: The tag resource relationship to delete.
97
+ """
98
+ zen_store().delete_tag_resource(tag_resource=tag_resource)
99
+
100
+
101
+ @router.delete(
102
+ BATCH,
103
+ responses={401: error_response, 404: error_response, 422: error_response},
104
+ )
105
+ @handle_exceptions
106
+ def batch_delete_tag_resource(
107
+ tag_resources: List[TagResourceRequest],
108
+ _: AuthContext = Security(authorize),
109
+ ) -> None:
110
+ """Detach different tags from different resources.
111
+
112
+ Args:
113
+ tag_resources: A list of tag resource requests.
114
+ """
115
+ zen_store().batch_delete_tag_resource(tag_resources=tag_resources)
@@ -33,13 +33,10 @@ from zenml.models import (
33
33
  from zenml.zen_server.auth import AuthContext, authorize
34
34
  from zenml.zen_server.exceptions import error_response
35
35
  from zenml.zen_server.rbac.endpoint_utils import (
36
- verify_permissions_and_create_entity,
37
36
  verify_permissions_and_delete_entity,
38
37
  verify_permissions_and_get_entity,
39
- verify_permissions_and_list_entities,
40
38
  verify_permissions_and_update_entity,
41
39
  )
42
- from zenml.zen_server.rbac.models import ResourceType
43
40
  from zenml.zen_server.utils import (
44
41
  handle_exceptions,
45
42
  make_dependable,
@@ -59,7 +56,6 @@ router = APIRouter(
59
56
 
60
57
  @router.post(
61
58
  "",
62
- response_model=TagResponse,
63
59
  responses={401: error_response, 409: error_response, 422: error_response},
64
60
  )
65
61
  @handle_exceptions
@@ -75,16 +71,11 @@ def create_tag(
75
71
  Returns:
76
72
  The created tag.
77
73
  """
78
- return verify_permissions_and_create_entity(
79
- request_model=tag,
80
- resource_type=ResourceType.TAG,
81
- create_method=zen_store().create_tag,
82
- )
74
+ return zen_store().create_tag(tag=tag)
83
75
 
84
76
 
85
77
  @router.get(
86
78
  "",
87
- response_model=Page[TagResponse],
88
79
  responses={401: error_response, 404: error_response, 422: error_response},
89
80
  )
90
81
  @handle_exceptions
@@ -104,17 +95,14 @@ def list_tags(
104
95
  Returns:
105
96
  The tags according to query filters.
106
97
  """
107
- return verify_permissions_and_list_entities(
108
- filter_model=tag_filter_model,
109
- resource_type=ResourceType.TAG,
110
- list_method=zen_store().list_tags,
98
+ return zen_store().list_tags(
99
+ tag_filter_model=tag_filter_model,
111
100
  hydrate=hydrate,
112
101
  )
113
102
 
114
103
 
115
104
  @router.get(
116
105
  "/{tag_name_or_id}",
117
- response_model=TagResponse,
118
106
  responses={401: error_response, 404: error_response, 422: error_response},
119
107
  )
120
108
  @handle_exceptions
@@ -134,13 +122,14 @@ def get_tag(
134
122
  The tag with the given name or ID.
135
123
  """
136
124
  return verify_permissions_and_get_entity(
137
- id=tag_name_or_id, get_method=zen_store().get_tag, hydrate=hydrate
125
+ id=tag_name_or_id,
126
+ get_method=zen_store().get_tag,
127
+ hydrate=hydrate,
138
128
  )
139
129
 
140
130
 
141
131
  @router.put(
142
132
  "/{tag_id}",
143
- response_model=TagResponse,
144
133
  responses={401: error_response, 404: error_response, 422: error_response},
145
134
  )
146
135
  @handle_exceptions