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 pipeline run schedules."""
15
15
 
16
+ from typing import Optional, Union
16
17
  from uuid import UUID
17
18
 
18
19
  from fastapi import APIRouter, Depends, Security
@@ -21,11 +22,16 @@ from zenml.constants import API, SCHEDULES, VERSION_1
21
22
  from zenml.models import (
22
23
  Page,
23
24
  ScheduleFilter,
25
+ ScheduleRequest,
24
26
  ScheduleResponse,
25
27
  ScheduleUpdate,
26
28
  )
27
29
  from zenml.zen_server.auth import AuthContext, authorize
28
30
  from zenml.zen_server.exceptions import error_response
31
+ from zenml.zen_server.rbac.endpoint_utils import (
32
+ verify_permissions_and_create_entity,
33
+ )
34
+ from zenml.zen_server.routers.projects_endpoints import workspace_router
29
35
  from zenml.zen_server.utils import (
30
36
  handle_exceptions,
31
37
  make_dependable,
@@ -39,16 +45,64 @@ router = APIRouter(
39
45
  )
40
46
 
41
47
 
48
+ @router.post(
49
+ "",
50
+ responses={401: error_response, 409: error_response, 422: error_response},
51
+ )
52
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
53
+ # and can be removed after the migration
54
+ @workspace_router.post(
55
+ "/{project_name_or_id}" + SCHEDULES,
56
+ responses={401: error_response, 409: error_response, 422: error_response},
57
+ deprecated=True,
58
+ tags=["schedules"],
59
+ )
60
+ @handle_exceptions
61
+ def create_schedule(
62
+ schedule: ScheduleRequest,
63
+ project_name_or_id: Optional[Union[str, UUID]] = None,
64
+ auth_context: AuthContext = Security(authorize),
65
+ ) -> ScheduleResponse:
66
+ """Creates a schedule.
67
+
68
+ Args:
69
+ schedule: Schedule to create.
70
+ project_name_or_id: Optional name or ID of the project.
71
+ auth_context: Authentication context.
72
+
73
+ Returns:
74
+ The created schedule.
75
+ """
76
+ if project_name_or_id:
77
+ project = zen_store().get_project(project_name_or_id)
78
+ schedule.project = project.id
79
+
80
+ # NOTE: no RBAC is enforced currently for schedules, but we're
81
+ # keeping the RBAC checks here for consistency
82
+ return verify_permissions_and_create_entity(
83
+ request_model=schedule,
84
+ create_method=zen_store().create_schedule,
85
+ )
86
+
87
+
42
88
  @router.get(
43
89
  "",
44
- response_model=Page[ScheduleResponse],
45
90
  responses={401: error_response, 404: error_response, 422: error_response},
46
91
  )
92
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
93
+ # and can be removed after the migration
94
+ @workspace_router.get(
95
+ "/{project_name_or_id}" + SCHEDULES,
96
+ responses={401: error_response, 404: error_response, 422: error_response},
97
+ deprecated=True,
98
+ tags=["schedules"],
99
+ )
47
100
  @handle_exceptions
48
101
  def list_schedules(
49
102
  schedule_filter_model: ScheduleFilter = Depends(
50
103
  make_dependable(ScheduleFilter)
51
104
  ),
105
+ project_name_or_id: Optional[Union[str, UUID]] = None,
52
106
  hydrate: bool = False,
53
107
  _: AuthContext = Security(authorize),
54
108
  ) -> Page[ScheduleResponse]:
@@ -57,20 +111,24 @@ def list_schedules(
57
111
  Args:
58
112
  schedule_filter_model: Filter model used for pagination, sorting,
59
113
  filtering
114
+ project_name_or_id: Optional name or ID of the project.
60
115
  hydrate: Flag deciding whether to hydrate the output model(s)
61
116
  by including metadata fields in the response.
62
117
 
63
118
  Returns:
64
119
  List of schedule objects.
65
120
  """
121
+ if project_name_or_id:
122
+ schedule_filter_model.project = project_name_or_id
123
+
66
124
  return zen_store().list_schedules(
67
- schedule_filter_model=schedule_filter_model, hydrate=hydrate
125
+ schedule_filter_model=schedule_filter_model,
126
+ hydrate=hydrate,
68
127
  )
69
128
 
70
129
 
71
130
  @router.get(
72
131
  "/{schedule_id}",
73
- response_model=ScheduleResponse,
74
132
  responses={401: error_response, 404: error_response, 422: error_response},
75
133
  )
76
134
  @handle_exceptions
@@ -89,12 +147,14 @@ def get_schedule(
89
147
  Returns:
90
148
  A specific schedule object.
91
149
  """
92
- return zen_store().get_schedule(schedule_id=schedule_id, hydrate=hydrate)
150
+ return zen_store().get_schedule(
151
+ schedule_id=schedule_id,
152
+ hydrate=hydrate,
153
+ )
93
154
 
94
155
 
95
156
  @router.put(
96
157
  "/{schedule_id}",
97
- response_model=ScheduleResponse,
98
158
  responses={401: error_response, 404: error_response, 422: error_response},
99
159
  )
100
160
  @handle_exceptions
@@ -113,7 +173,8 @@ def update_schedule(
113
173
  The updated schedule object.
114
174
  """
115
175
  return zen_store().update_schedule(
116
- schedule_id=schedule_id, schedule_update=schedule_update
176
+ schedule_id=schedule_id,
177
+ schedule_update=schedule_update,
117
178
  )
118
179
 
119
180
 
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Endpoint definitions for pipeline run secrets."""
15
15
 
16
- from typing import Optional
16
+ from typing import Optional, Union
17
17
  from uuid import UUID
18
18
 
19
19
  from fastapi import APIRouter, Depends, Security
@@ -29,12 +29,14 @@ from zenml.constants import (
29
29
  from zenml.models import (
30
30
  Page,
31
31
  SecretFilter,
32
+ SecretRequest,
32
33
  SecretResponse,
33
34
  SecretUpdate,
34
35
  )
35
36
  from zenml.zen_server.auth import AuthContext, authorize
36
37
  from zenml.zen_server.exceptions import error_response
37
38
  from zenml.zen_server.rbac.endpoint_utils import (
39
+ verify_permissions_and_create_entity,
38
40
  verify_permissions_and_delete_entity,
39
41
  verify_permissions_and_get_entity,
40
42
  verify_permissions_and_list_entities,
@@ -47,6 +49,7 @@ from zenml.zen_server.rbac.utils import (
47
49
  is_owned_by_authenticated_user,
48
50
  verify_permission,
49
51
  )
52
+ from zenml.zen_server.routers.projects_endpoints import workspace_router
50
53
  from zenml.zen_server.utils import (
51
54
  handle_exceptions,
52
55
  make_dependable,
@@ -66,9 +69,41 @@ op_router = APIRouter(
66
69
  )
67
70
 
68
71
 
72
+ @router.post(
73
+ "",
74
+ responses={401: error_response, 409: error_response, 422: error_response},
75
+ )
76
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
77
+ # and can be removed after the migration
78
+ @workspace_router.post(
79
+ "/{workspace_name_or_id}" + SECRETS,
80
+ responses={401: error_response, 409: error_response, 422: error_response},
81
+ deprecated=True,
82
+ tags=["secrets"],
83
+ )
84
+ @handle_exceptions
85
+ def create_secret(
86
+ secret: SecretRequest,
87
+ workspace_name_or_id: Optional[Union[str, UUID]] = None,
88
+ _: AuthContext = Security(authorize),
89
+ ) -> SecretResponse:
90
+ """Creates a secret.
91
+
92
+ Args:
93
+ secret: Secret to create.
94
+ workspace_name_or_id: Optional name or ID of the workspace.
95
+
96
+ Returns:
97
+ The created secret.
98
+ """
99
+ return verify_permissions_and_create_entity(
100
+ request_model=secret,
101
+ create_method=zen_store().create_secret,
102
+ )
103
+
104
+
69
105
  @router.get(
70
106
  "",
71
- response_model=Page[SecretResponse],
72
107
  responses={401: error_response, 404: error_response, 422: error_response},
73
108
  )
74
109
  @handle_exceptions
@@ -116,7 +151,6 @@ def list_secrets(
116
151
 
117
152
  @router.get(
118
153
  "/{secret_id}",
119
- response_model=SecretResponse,
120
154
  responses={401: error_response, 404: error_response, 422: error_response},
121
155
  )
122
156
  @handle_exceptions
@@ -140,6 +174,7 @@ def get_secret(
140
174
  get_method=zen_store().get_secret,
141
175
  hydrate=hydrate,
142
176
  )
177
+
143
178
  if not has_permissions_for_model(secret, action=Action.READ_SECRET_VALUE):
144
179
  secret.remove_secrets()
145
180
 
@@ -148,7 +183,6 @@ def get_secret(
148
183
 
149
184
  @router.put(
150
185
  "/{secret_id}",
151
- response_model=SecretResponse,
152
186
  responses={401: error_response, 404: error_response, 422: error_response},
153
187
  )
154
188
  @handle_exceptions
@@ -25,20 +25,27 @@ from zenml.constants import (
25
25
  LOAD_INFO,
26
26
  ONBOARDING_STATE,
27
27
  SERVER_SETTINGS,
28
+ STATISTICS,
28
29
  VERSION_1,
29
30
  )
30
31
  from zenml.enums import AuthScheme
31
32
  from zenml.exceptions import IllegalOperationError
32
33
  from zenml.models import (
34
+ ComponentFilter,
35
+ ProjectFilter,
33
36
  ServerActivationRequest,
34
37
  ServerLoadInfo,
35
38
  ServerModel,
36
39
  ServerSettingsResponse,
37
40
  ServerSettingsUpdate,
41
+ ServerStatistics,
42
+ StackFilter,
38
43
  UserResponse,
39
44
  )
40
45
  from zenml.zen_server.auth import AuthContext, authorize
41
46
  from zenml.zen_server.exceptions import error_response
47
+ from zenml.zen_server.rbac.models import ResourceType
48
+ from zenml.zen_server.rbac.utils import get_allowed_resource_ids
42
49
  from zenml.zen_server.utils import handle_exceptions, server_config, zen_store
43
50
 
44
51
  router = APIRouter(
@@ -60,7 +67,6 @@ def version() -> str:
60
67
 
61
68
  @router.get(
62
69
  INFO,
63
- response_model=ServerModel,
64
70
  responses={401: error_response, 404: error_response, 422: error_response},
65
71
  )
66
72
  @handle_exceptions
@@ -234,3 +240,49 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
234
240
  The default admin user that was created during activation, if any.
235
241
  """
236
242
  return zen_store().activate_server(activate_request)
243
+
244
+
245
+ @router.get(
246
+ STATISTICS,
247
+ responses={401: error_response, 404: error_response, 422: error_response},
248
+ )
249
+ @handle_exceptions
250
+ def get_server_statistics(
251
+ auth_context: AuthContext = Security(authorize),
252
+ ) -> ServerStatistics:
253
+ """Gets server statistics.
254
+
255
+ Args:
256
+ auth_context: Authentication context.
257
+
258
+ Returns:
259
+ Statistics of the server.
260
+ """
261
+ user_id = auth_context.user.id
262
+ component_filter = ComponentFilter()
263
+ component_filter.configure_rbac(
264
+ authenticated_user_id=user_id,
265
+ id=get_allowed_resource_ids(
266
+ resource_type=ResourceType.STACK_COMPONENT
267
+ ),
268
+ )
269
+
270
+ project_filter = ProjectFilter()
271
+ project_filter.configure_rbac(
272
+ authenticated_user_id=user_id,
273
+ id=get_allowed_resource_ids(resource_type=ResourceType.PROJECT),
274
+ )
275
+
276
+ stack_filter = StackFilter()
277
+ stack_filter.configure_rbac(
278
+ authenticated_user_id=user_id,
279
+ id=get_allowed_resource_ids(resource_type=ResourceType.STACK),
280
+ )
281
+
282
+ return ServerStatistics(
283
+ stacks=zen_store().count_stacks(filter_model=stack_filter),
284
+ components=zen_store().count_stack_components(
285
+ filter_model=component_filter
286
+ ),
287
+ projects=zen_store().count_projects(filter_model=project_filter),
288
+ )
@@ -67,7 +67,6 @@ router = APIRouter(
67
67
 
68
68
  @router.post(
69
69
  "",
70
- response_model=ServiceAccountResponse,
71
70
  responses={
72
71
  401: error_response,
73
72
  409: error_response,
@@ -89,14 +88,12 @@ def create_service_account(
89
88
  """
90
89
  return verify_permissions_and_create_entity(
91
90
  request_model=service_account,
92
- resource_type=ResourceType.SERVICE_ACCOUNT,
93
91
  create_method=zen_store().create_service_account,
94
92
  )
95
93
 
96
94
 
97
95
  @router.get(
98
96
  "/{service_account_name_or_id}",
99
- response_model=ServiceAccountResponse,
100
97
  responses={401: error_response, 404: error_response, 422: error_response},
101
98
  )
102
99
  @handle_exceptions
@@ -124,7 +121,6 @@ def get_service_account(
124
121
 
125
122
  @router.get(
126
123
  "",
127
- response_model=Page[ServiceAccountResponse],
128
124
  responses={401: error_response, 404: error_response, 422: error_response},
129
125
  )
130
126
  @handle_exceptions
@@ -156,7 +152,6 @@ def list_service_accounts(
156
152
 
157
153
  @router.put(
158
154
  "/{service_account_name_or_id}",
159
- response_model=ServiceAccountResponse,
160
155
  responses={
161
156
  401: error_response,
162
157
  404: error_response,
@@ -214,7 +209,6 @@ def delete_service_account(
214
209
 
215
210
  @router.post(
216
211
  "/{service_account_id}" + API_KEYS,
217
- response_model=APIKeyResponse,
218
212
  responses={401: error_response, 409: error_response, 422: error_response},
219
213
  )
220
214
  @handle_exceptions
@@ -233,18 +227,26 @@ def create_api_key(
233
227
  Returns:
234
228
  The created API key.
235
229
  """
230
+
231
+ def create_api_key_wrapper(
232
+ api_key: APIKeyRequest,
233
+ ) -> APIKeyResponse:
234
+ return zen_store().create_api_key(
235
+ service_account_id=service_account_id,
236
+ api_key=api_key,
237
+ )
238
+
236
239
  service_account = zen_store().get_service_account(service_account_id)
237
- verify_permission_for_model(service_account, action=Action.UPDATE)
238
- created_api_key = zen_store().create_api_key(
239
- service_account_id=service_account_id,
240
- api_key=api_key,
240
+
241
+ return verify_permissions_and_create_entity(
242
+ request_model=api_key,
243
+ create_method=create_api_key_wrapper,
244
+ surrogate_models=[service_account],
241
245
  )
242
- return created_api_key
243
246
 
244
247
 
245
248
  @router.get(
246
249
  "/{service_account_id}" + API_KEYS + "/{api_key_name_or_id}",
247
- response_model=APIKeyResponse,
248
250
  responses={401: error_response, 404: error_response, 422: error_response},
249
251
  )
250
252
  @handle_exceptions
@@ -278,7 +280,6 @@ def get_api_key(
278
280
 
279
281
  @router.get(
280
282
  "/{service_account_id}" + API_KEYS,
281
- response_model=Page[APIKeyResponse],
282
283
  responses={401: error_response, 404: error_response, 422: error_response},
283
284
  )
284
285
  @handle_exceptions
@@ -313,7 +314,6 @@ def list_api_keys(
313
314
 
314
315
  @router.put(
315
316
  "/{service_account_id}" + API_KEYS + "/{api_key_name_or_id}",
316
- response_model=APIKeyResponse,
317
317
  responses={401: error_response, 409: error_response, 422: error_response},
318
318
  )
319
319
  @handle_exceptions
@@ -348,7 +348,6 @@ def update_api_key(
348
348
  + API_KEYS
349
349
  + "/{api_key_name_or_id}"
350
350
  + API_KEY_ROTATE,
351
- response_model=APIKeyResponse,
352
351
  responses={401: error_response, 409: error_response, 422: error_response},
353
352
  )
354
353
  @handle_exceptions
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Endpoint definitions for service connectors."""
15
15
 
16
- from typing import List, Optional
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 (
22
22
  API,
23
23
  SERVICE_CONNECTOR_CLIENT,
24
24
  SERVICE_CONNECTOR_FULL_STACK,
25
+ SERVICE_CONNECTOR_RESOURCES,
25
26
  SERVICE_CONNECTOR_TYPES,
26
27
  SERVICE_CONNECTOR_VERIFY,
27
28
  SERVICE_CONNECTORS,
@@ -44,6 +45,7 @@ from zenml.service_connectors.service_connector_utils import (
44
45
  from zenml.zen_server.auth import AuthContext, authorize
45
46
  from zenml.zen_server.exceptions import error_response
46
47
  from zenml.zen_server.rbac.endpoint_utils import (
48
+ verify_permissions_and_create_entity,
47
49
  verify_permissions_and_delete_entity,
48
50
  verify_permissions_and_list_entities,
49
51
  verify_permissions_and_update_entity,
@@ -57,6 +59,7 @@ from zenml.zen_server.rbac.utils import (
57
59
  verify_permission,
58
60
  verify_permission_for_model,
59
61
  )
62
+ from zenml.zen_server.routers.projects_endpoints import workspace_router
60
63
  from zenml.zen_server.utils import (
61
64
  handle_exceptions,
62
65
  make_dependable,
@@ -76,31 +79,73 @@ types_router = APIRouter(
76
79
  )
77
80
 
78
81
 
82
+ @router.post(
83
+ "",
84
+ responses={401: error_response, 409: error_response, 422: error_response},
85
+ )
86
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
87
+ # and can be removed after the migration
88
+ @workspace_router.post(
89
+ "/{project_name_or_id}" + SERVICE_CONNECTORS,
90
+ responses={401: error_response, 409: error_response, 422: error_response},
91
+ deprecated=True,
92
+ tags=["service_connectors"],
93
+ )
94
+ @handle_exceptions
95
+ def create_service_connector(
96
+ connector: ServiceConnectorRequest,
97
+ project_name_or_id: Optional[Union[str, UUID]] = None,
98
+ _: AuthContext = Security(authorize),
99
+ ) -> ServiceConnectorResponse:
100
+ """Creates a service connector.
101
+
102
+ Args:
103
+ connector: Service connector to register.
104
+ project_name_or_id: Optional name or ID of the project.
105
+
106
+ Returns:
107
+ The created service connector.
108
+ """
109
+ return verify_permissions_and_create_entity(
110
+ request_model=connector,
111
+ create_method=zen_store().create_service_connector,
112
+ )
113
+
114
+
79
115
  @router.get(
80
116
  "",
81
- response_model=Page[ServiceConnectorResponse],
82
117
  responses={401: error_response, 404: error_response, 422: error_response},
83
118
  )
119
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
120
+ # and can be removed after the migration
121
+ @workspace_router.get(
122
+ "/{project_name_or_id}" + SERVICE_CONNECTORS,
123
+ responses={401: error_response, 404: error_response, 422: error_response},
124
+ deprecated=True,
125
+ tags=["service_connectors"],
126
+ )
84
127
  @handle_exceptions
85
128
  def list_service_connectors(
86
129
  connector_filter_model: ServiceConnectorFilter = Depends(
87
130
  make_dependable(ServiceConnectorFilter)
88
131
  ),
132
+ project_name_or_id: Optional[Union[str, UUID]] = None,
89
133
  expand_secrets: bool = True,
90
134
  hydrate: bool = False,
91
135
  _: AuthContext = Security(authorize),
92
136
  ) -> Page[ServiceConnectorResponse]:
93
- """Get a list of all service connectors for a specific type.
137
+ """Get a list of all service connectors.
94
138
 
95
139
  Args:
96
140
  connector_filter_model: Filter model used for pagination, sorting,
97
141
  filtering
142
+ project_name_or_id: Optional name or ID of the project to filter by.
98
143
  expand_secrets: Whether to expand secrets or not.
99
144
  hydrate: Flag deciding whether to hydrate the output model(s)
100
145
  by including metadata fields in the response.
101
146
 
102
147
  Returns:
103
- Page with list of service connectors for a specific type.
148
+ Page with list of service connectors matching the filter criteria.
104
149
  """
105
150
  connectors = verify_permissions_and_list_entities(
106
151
  filter_model=connector_filter_model,
@@ -143,7 +188,6 @@ def list_service_connectors(
143
188
 
144
189
  @router.get(
145
190
  "/{connector_id}",
146
- response_model=ServiceConnectorResponse,
147
191
  responses={401: error_response, 404: error_response, 422: error_response},
148
192
  )
149
193
  @handle_exceptions
@@ -186,7 +230,6 @@ def get_service_connector(
186
230
 
187
231
  @router.put(
188
232
  "/{connector_id}",
189
- response_model=ServiceConnectorResponse,
190
233
  responses={401: error_response, 404: error_response, 422: error_response},
191
234
  )
192
235
  @handle_exceptions
@@ -235,7 +278,6 @@ def delete_service_connector(
235
278
 
236
279
  @router.post(
237
280
  SERVICE_CONNECTOR_VERIFY,
238
- response_model=ServiceConnectorResourcesModel,
239
281
  responses={401: error_response, 409: error_response, 422: error_response},
240
282
  )
241
283
  @handle_exceptions
@@ -259,9 +301,7 @@ def validate_and_verify_service_connector_config(
259
301
  The list of resources that the service connector configuration has
260
302
  access to.
261
303
  """
262
- verify_permission(
263
- resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
264
- )
304
+ verify_permission_for_model(model=connector, action=Action.CREATE)
265
305
 
266
306
  return zen_store().verify_service_connector_config(
267
307
  service_connector=connector,
@@ -269,9 +309,52 @@ def validate_and_verify_service_connector_config(
269
309
  )
270
310
 
271
311
 
312
+ @router.get(
313
+ SERVICE_CONNECTOR_RESOURCES,
314
+ responses={401: error_response, 404: error_response, 422: error_response},
315
+ )
316
+ # TODO: the workspace scoped endpoint is only kept for dashboard compatibility
317
+ # and can be removed after the migration
318
+ @workspace_router.get(
319
+ "/{project_name_or_id}" + SERVICE_CONNECTOR_RESOURCES,
320
+ responses={401: error_response, 404: error_response, 422: error_response},
321
+ deprecated=True,
322
+ tags=["service_connectors"],
323
+ )
324
+ @handle_exceptions
325
+ def list_service_connector_resources(
326
+ filter_model: ServiceConnectorFilter = Depends(
327
+ make_dependable(ServiceConnectorFilter)
328
+ ),
329
+ project_name_or_id: Optional[Union[str, UUID]] = None,
330
+ auth_context: AuthContext = Security(authorize),
331
+ ) -> List[ServiceConnectorResourcesModel]:
332
+ """List resources that can be accessed by service connectors.
333
+
334
+ Args:
335
+ filter_model: The filter model to use when fetching service
336
+ connectors.
337
+ project_name_or_id: Optional name or ID of the project.
338
+ auth_context: Authentication context.
339
+
340
+ Returns:
341
+ The matching list of resources that available service
342
+ connectors have access to.
343
+ """
344
+ allowed_ids = get_allowed_resource_ids(
345
+ resource_type=ResourceType.SERVICE_CONNECTOR
346
+ )
347
+ filter_model.configure_rbac(
348
+ authenticated_user_id=auth_context.user.id, id=allowed_ids
349
+ )
350
+
351
+ return zen_store().list_service_connector_resources(
352
+ filter_model=filter_model,
353
+ )
354
+
355
+
272
356
  @router.put(
273
357
  "/{connector_id}" + SERVICE_CONNECTOR_VERIFY,
274
- response_model=ServiceConnectorResourcesModel,
275
358
  responses={401: error_response, 404: error_response, 422: error_response},
276
359
  )
277
360
  @handle_exceptions
@@ -313,7 +396,6 @@ def validate_and_verify_service_connector(
313
396
 
314
397
  @router.get(
315
398
  "/{connector_id}" + SERVICE_CONNECTOR_CLIENT,
316
- response_model=ServiceConnectorResponse,
317
399
  responses={401: error_response, 404: error_response, 422: error_response},
318
400
  )
319
401
  @handle_exceptions
@@ -351,7 +433,6 @@ def get_service_connector_client(
351
433
 
352
434
  @types_router.get(
353
435
  "",
354
- response_model=List[ServiceConnectorTypeModel],
355
436
  responses={401: error_response, 404: error_response, 422: error_response},
356
437
  )
357
438
  @handle_exceptions
@@ -382,7 +463,6 @@ def list_service_connector_types(
382
463
 
383
464
  @types_router.get(
384
465
  "/{connector_type}",
385
- response_model=ServiceConnectorTypeModel,
386
466
  responses={401: error_response, 404: error_response, 422: error_response},
387
467
  )
388
468
  @handle_exceptions