zenml-nightly 0.75.0.dev20250311__py3-none-any.whl → 0.75.0.dev20250313__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zenml/VERSION +1 -1
- zenml/__init__.py +2 -0
- zenml/analytics/context.py +7 -0
- zenml/artifacts/utils.py +0 -2
- zenml/cli/login.py +6 -0
- zenml/cli/model.py +7 -15
- zenml/cli/secret.py +47 -44
- zenml/cli/service_connectors.py +0 -1
- zenml/cli/stack.py +0 -1
- zenml/cli/tag.py +3 -5
- zenml/cli/utils.py +25 -23
- zenml/cli/workspace.py +79 -5
- zenml/client.py +618 -348
- zenml/config/global_config.py +16 -3
- zenml/config/pipeline_configurations.py +3 -2
- zenml/config/pipeline_run_configuration.py +2 -1
- zenml/config/secret_reference_mixin.py +1 -1
- zenml/constants.py +1 -3
- zenml/enums.py +0 -7
- zenml/event_hub/event_hub.py +3 -1
- zenml/exceptions.py +0 -24
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +5 -3
- zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +1 -4
- zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +1 -4
- zenml/integrations/mlflow/steps/mlflow_registry.py +1 -1
- zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -1
- zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +3 -3
- zenml/model/model.py +8 -8
- zenml/models/__init__.py +18 -1
- zenml/models/v2/base/base.py +0 -5
- zenml/models/v2/base/filter.py +1 -1
- zenml/models/v2/base/scoped.py +104 -121
- zenml/models/v2/core/api_key.py +1 -1
- zenml/models/v2/core/artifact.py +31 -18
- zenml/models/v2/core/artifact_version.py +42 -25
- zenml/models/v2/core/component.py +22 -33
- zenml/models/v2/core/device.py +3 -2
- zenml/models/v2/core/event_source.py +2 -2
- zenml/models/v2/core/flavor.py +19 -47
- zenml/models/v2/core/logs.py +1 -2
- zenml/models/v2/core/model.py +7 -4
- zenml/models/v2/core/model_version.py +36 -27
- zenml/models/v2/core/pipeline.py +1 -1
- zenml/models/v2/core/pipeline_build.py +18 -0
- zenml/models/v2/core/pipeline_run.py +5 -13
- zenml/models/v2/core/run_template.py +1 -2
- zenml/models/v2/core/schedule.py +0 -9
- zenml/models/v2/core/secret.py +93 -127
- zenml/models/v2/core/server_settings.py +2 -2
- zenml/models/v2/core/service.py +43 -12
- zenml/models/v2/core/service_connector.py +14 -16
- zenml/models/v2/core/stack.py +24 -26
- zenml/models/v2/core/step_run.py +3 -15
- zenml/models/v2/core/tag.py +41 -15
- zenml/models/v2/core/user.py +19 -2
- zenml/models/v2/misc/statistics.py +45 -0
- zenml/models/v2/misc/tag.py +27 -0
- zenml/orchestrators/cache_utils.py +1 -1
- zenml/orchestrators/input_utils.py +1 -0
- zenml/orchestrators/step_launcher.py +0 -1
- zenml/orchestrators/step_run_utils.py +0 -2
- zenml/orchestrators/step_runner.py +10 -1
- zenml/pipelines/build_utils.py +4 -2
- zenml/pipelines/pipeline_decorator.py +3 -2
- zenml/pipelines/pipeline_definition.py +4 -5
- zenml/pipelines/run_utils.py +3 -3
- zenml/service_connectors/service_connector.py +0 -7
- zenml/service_connectors/service_connector_utils.py +0 -1
- zenml/stack/authentication_mixin.py +1 -1
- zenml/stack/flavor.py +3 -14
- zenml/stack/stack_component.py +1 -5
- zenml/steps/step_context.py +19 -0
- zenml/utils/string_utils.py +1 -1
- zenml/utils/tag_utils.py +642 -0
- zenml/zen_server/cloud_utils.py +21 -0
- zenml/zen_server/exceptions.py +0 -6
- zenml/zen_server/rbac/endpoint_utils.py +134 -46
- zenml/zen_server/rbac/models.py +65 -3
- zenml/zen_server/rbac/rbac_interface.py +9 -0
- zenml/zen_server/rbac/rbac_sql_zen_store.py +15 -7
- zenml/zen_server/rbac/utils.py +156 -29
- zenml/zen_server/rbac/zenml_cloud_rbac.py +43 -11
- zenml/zen_server/routers/actions_endpoints.py +3 -5
- zenml/zen_server/routers/artifact_endpoint.py +0 -5
- zenml/zen_server/routers/artifact_version_endpoints.py +15 -9
- zenml/zen_server/routers/auth_endpoints.py +22 -7
- zenml/zen_server/routers/code_repositories_endpoints.py +56 -3
- zenml/zen_server/routers/devices_endpoints.py +0 -4
- zenml/zen_server/routers/event_source_endpoints.py +0 -5
- zenml/zen_server/routers/flavors_endpoints.py +0 -5
- zenml/zen_server/routers/logs_endpoints.py +0 -1
- zenml/zen_server/routers/model_versions_endpoints.py +102 -23
- zenml/zen_server/routers/models_endpoints.py +51 -68
- zenml/zen_server/routers/pipeline_builds_endpoints.py +58 -4
- zenml/zen_server/routers/pipeline_deployments_endpoints.py +58 -4
- zenml/zen_server/routers/pipelines_endpoints.py +73 -4
- zenml/zen_server/routers/plugin_endpoints.py +0 -1
- zenml/zen_server/routers/run_metadata_endpoints.py +99 -0
- zenml/zen_server/routers/run_templates_endpoints.py +66 -3
- zenml/zen_server/routers/runs_endpoints.py +60 -8
- zenml/zen_server/routers/schedule_endpoints.py +69 -6
- zenml/zen_server/routers/secrets_endpoints.py +40 -4
- zenml/zen_server/routers/server_endpoints.py +53 -1
- zenml/zen_server/routers/service_accounts_endpoints.py +14 -15
- zenml/zen_server/routers/service_connectors_endpoints.py +96 -14
- zenml/zen_server/routers/service_endpoints.py +20 -7
- zenml/zen_server/routers/stack_components_endpoints.py +68 -7
- zenml/zen_server/routers/stacks_endpoints.py +98 -7
- zenml/zen_server/routers/steps_endpoints.py +17 -11
- zenml/zen_server/routers/tag_resource_endpoints.py +115 -0
- zenml/zen_server/routers/tags_endpoints.py +6 -17
- zenml/zen_server/routers/triggers_endpoints.py +5 -8
- zenml/zen_server/routers/users_endpoints.py +47 -12
- zenml/zen_server/routers/workspaces_endpoints.py +56 -1285
- zenml/zen_server/template_execution/utils.py +5 -4
- zenml/zen_server/utils.py +21 -0
- zenml/zen_server/zen_server_api.py +4 -0
- zenml/zen_stores/base_zen_store.py +29 -44
- zenml/zen_stores/migrations/versions/0392807467dc_add_build_duration.py +34 -0
- zenml/zen_stores/migrations/versions/1cb6477f72d6_move_artifact_save_type.py +20 -10
- zenml/zen_stores/migrations/versions/1f9d1cd00b90_add_unique_name_constraints.py +231 -0
- zenml/zen_stores/migrations/versions/288f4fb6e112_make_tags_user_scoped.py +74 -0
- zenml/zen_stores/migrations/versions/2e695a26fe7a_add_user_default_workspace.py +45 -0
- zenml/zen_stores/migrations/versions/3b1776345020_remove_workspace_from_globals.py +81 -0
- zenml/zen_stores/migrations/versions/41b28cae31ce_make_artifacts_workspace_scoped.py +136 -0
- zenml/zen_stores/migrations/versions/9e7bf0970266_adding_exclusive_attribute_to_tags.py +47 -0
- zenml/zen_stores/migrations/versions/b557b2871693_update_step_run_input_types.py +8 -4
- zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +12 -6
- zenml/zen_stores/migrations/versions/f1d723fd723b_add_secret_private_attr.py +61 -0
- zenml/zen_stores/migrations/versions/f76a368a25a5_add_stack_description.py +35 -0
- zenml/zen_stores/rest_zen_store.py +172 -171
- zenml/zen_stores/schemas/action_schemas.py +8 -1
- zenml/zen_stores/schemas/api_key_schemas.py +8 -1
- zenml/zen_stores/schemas/artifact_schemas.py +28 -1
- zenml/zen_stores/schemas/code_repository_schemas.py +8 -1
- zenml/zen_stores/schemas/component_schemas.py +9 -14
- zenml/zen_stores/schemas/event_source_schemas.py +8 -1
- zenml/zen_stores/schemas/flavor_schemas.py +14 -20
- zenml/zen_stores/schemas/model_schemas.py +3 -0
- zenml/zen_stores/schemas/pipeline_build_schemas.py +4 -0
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +3 -1
- zenml/zen_stores/schemas/pipeline_run_schemas.py +0 -3
- zenml/zen_stores/schemas/run_template_schemas.py +8 -4
- zenml/zen_stores/schemas/schedule_schema.py +9 -14
- zenml/zen_stores/schemas/secret_schemas.py +15 -25
- zenml/zen_stores/schemas/service_connector_schemas.py +8 -17
- zenml/zen_stores/schemas/service_schemas.py +0 -1
- zenml/zen_stores/schemas/stack_schemas.py +12 -15
- zenml/zen_stores/schemas/step_run_schemas.py +7 -8
- zenml/zen_stores/schemas/tag_schemas.py +30 -2
- zenml/zen_stores/schemas/trigger_schemas.py +8 -1
- zenml/zen_stores/schemas/user_schemas.py +24 -2
- zenml/zen_stores/schemas/utils.py +16 -0
- zenml/zen_stores/schemas/workspace_schemas.py +7 -25
- zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +0 -3
- zenml/zen_stores/sql_zen_store.py +2905 -2280
- zenml/zen_stores/template_utils.py +1 -1
- zenml/zen_stores/zen_store_interface.py +82 -58
- {zenml_nightly-0.75.0.dev20250311.dist-info → zenml_nightly-0.75.0.dev20250313.dist-info}/METADATA +1 -1
- {zenml_nightly-0.75.0.dev20250311.dist-info → zenml_nightly-0.75.0.dev20250313.dist-info}/RECORD +163 -149
- {zenml_nightly-0.75.0.dev20250311.dist-info → zenml_nightly-0.75.0.dev20250313.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.75.0.dev20250311.dist-info → zenml_nightly-0.75.0.dev20250313.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.75.0.dev20250311.dist-info → zenml_nightly-0.75.0.dev20250313.dist-info}/entry_points.txt +0 -0
@@ -13,38 +13,36 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for models."""
|
15
15
|
|
16
|
-
from typing import Union
|
16
|
+
from typing import Optional, Union
|
17
17
|
from uuid import UUID
|
18
18
|
|
19
19
|
from fastapi import APIRouter, Depends, Security
|
20
20
|
|
21
21
|
from zenml.constants import (
|
22
22
|
API,
|
23
|
-
MODEL_VERSIONS,
|
24
23
|
MODELS,
|
25
24
|
VERSION_1,
|
26
25
|
)
|
27
26
|
from zenml.models import (
|
28
27
|
ModelFilter,
|
28
|
+
ModelRequest,
|
29
29
|
ModelResponse,
|
30
30
|
ModelUpdate,
|
31
|
-
ModelVersionFilter,
|
32
|
-
ModelVersionResponse,
|
33
31
|
Page,
|
34
32
|
)
|
35
33
|
from zenml.zen_server.auth import AuthContext, authorize
|
36
34
|
from zenml.zen_server.exceptions import error_response
|
37
35
|
from zenml.zen_server.feature_gate.endpoint_utils import report_decrement
|
38
36
|
from zenml.zen_server.rbac.endpoint_utils import (
|
37
|
+
verify_permissions_and_create_entity,
|
39
38
|
verify_permissions_and_delete_entity,
|
40
39
|
verify_permissions_and_get_entity,
|
41
40
|
verify_permissions_and_list_entities,
|
42
41
|
verify_permissions_and_update_entity,
|
43
42
|
)
|
44
43
|
from zenml.zen_server.rbac.models import ResourceType
|
45
|
-
from zenml.zen_server.
|
46
|
-
|
47
|
-
get_allowed_resource_ids,
|
44
|
+
from zenml.zen_server.routers.workspaces_endpoints import (
|
45
|
+
router as workspace_router,
|
48
46
|
)
|
49
47
|
from zenml.zen_server.utils import (
|
50
48
|
handle_exceptions,
|
@@ -64,9 +62,45 @@ router = APIRouter(
|
|
64
62
|
)
|
65
63
|
|
66
64
|
|
65
|
+
@router.post(
|
66
|
+
"",
|
67
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
68
|
+
)
|
69
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
70
|
+
# and can be removed after the migration
|
71
|
+
@workspace_router.post(
|
72
|
+
"/{workspace_name_or_id}" + MODELS,
|
73
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
74
|
+
deprecated=True,
|
75
|
+
tags=["models"],
|
76
|
+
)
|
77
|
+
@handle_exceptions
|
78
|
+
def create_model(
|
79
|
+
model: ModelRequest,
|
80
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
81
|
+
_: AuthContext = Security(authorize),
|
82
|
+
) -> ModelResponse:
|
83
|
+
"""Creates a model.
|
84
|
+
|
85
|
+
Args:
|
86
|
+
model: Model to create.
|
87
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
88
|
+
|
89
|
+
Returns:
|
90
|
+
The created model.
|
91
|
+
"""
|
92
|
+
if workspace_name_or_id:
|
93
|
+
workspace = zen_store().get_workspace(workspace_name_or_id)
|
94
|
+
model.workspace = workspace.id
|
95
|
+
|
96
|
+
return verify_permissions_and_create_entity(
|
97
|
+
request_model=model,
|
98
|
+
create_method=zen_store().create_model,
|
99
|
+
)
|
100
|
+
|
101
|
+
|
67
102
|
@router.get(
|
68
103
|
"",
|
69
|
-
response_model=Page[ModelResponse],
|
70
104
|
responses={401: error_response, 404: error_response, 422: error_response},
|
71
105
|
)
|
72
106
|
@handle_exceptions
|
@@ -95,20 +129,19 @@ def list_models(
|
|
95
129
|
|
96
130
|
|
97
131
|
@router.get(
|
98
|
-
"/{
|
99
|
-
response_model=ModelResponse,
|
132
|
+
"/{model_id}",
|
100
133
|
responses={401: error_response, 404: error_response, 422: error_response},
|
101
134
|
)
|
102
135
|
@handle_exceptions
|
103
136
|
def get_model(
|
104
|
-
|
137
|
+
model_id: UUID,
|
105
138
|
hydrate: bool = True,
|
106
139
|
_: AuthContext = Security(authorize),
|
107
140
|
) -> ModelResponse:
|
108
141
|
"""Get a model by name or ID.
|
109
142
|
|
110
143
|
Args:
|
111
|
-
|
144
|
+
model_id: The ID of the model to get.
|
112
145
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
113
146
|
by including metadata fields in the response.
|
114
147
|
|
@@ -116,13 +149,12 @@ def get_model(
|
|
116
149
|
The model with the given name or ID.
|
117
150
|
"""
|
118
151
|
return verify_permissions_and_get_entity(
|
119
|
-
id=
|
152
|
+
id=model_id, get_method=zen_store().get_model, hydrate=hydrate
|
120
153
|
)
|
121
154
|
|
122
155
|
|
123
156
|
@router.put(
|
124
157
|
"/{model_id}",
|
125
|
-
response_model=ModelResponse,
|
126
158
|
responses={401: error_response, 404: error_response, 422: error_response},
|
127
159
|
)
|
128
160
|
@handle_exceptions
|
@@ -149,21 +181,21 @@ def update_model(
|
|
149
181
|
|
150
182
|
|
151
183
|
@router.delete(
|
152
|
-
"/{
|
184
|
+
"/{model_id}",
|
153
185
|
responses={401: error_response, 404: error_response, 422: error_response},
|
154
186
|
)
|
155
187
|
@handle_exceptions
|
156
188
|
def delete_model(
|
157
|
-
|
189
|
+
model_id: UUID,
|
158
190
|
_: AuthContext = Security(authorize),
|
159
191
|
) -> None:
|
160
|
-
"""Delete a model by
|
192
|
+
"""Delete a model by ID.
|
161
193
|
|
162
194
|
Args:
|
163
|
-
|
195
|
+
model_id: The ID of the model to delete.
|
164
196
|
"""
|
165
197
|
model = verify_permissions_and_delete_entity(
|
166
|
-
id=
|
198
|
+
id=model_id,
|
167
199
|
get_method=zen_store().get_model,
|
168
200
|
delete_method=zen_store().delete_model,
|
169
201
|
)
|
@@ -171,52 +203,3 @@ def delete_model(
|
|
171
203
|
if server_config().feature_gate_enabled:
|
172
204
|
if ResourceType.MODEL in server_config().reportable_resources:
|
173
205
|
report_decrement(ResourceType.MODEL, resource_id=model.id)
|
174
|
-
|
175
|
-
|
176
|
-
#################
|
177
|
-
# Model Versions
|
178
|
-
#################
|
179
|
-
|
180
|
-
|
181
|
-
@router.get(
|
182
|
-
"/{model_name_or_id}" + MODEL_VERSIONS,
|
183
|
-
response_model=Page[ModelVersionResponse],
|
184
|
-
responses={401: error_response, 404: error_response, 422: error_response},
|
185
|
-
)
|
186
|
-
@handle_exceptions
|
187
|
-
def list_model_versions(
|
188
|
-
model_name_or_id: Union[str, UUID],
|
189
|
-
model_version_filter_model: ModelVersionFilter = Depends(
|
190
|
-
make_dependable(ModelVersionFilter)
|
191
|
-
),
|
192
|
-
hydrate: bool = False,
|
193
|
-
auth_context: AuthContext = Security(authorize),
|
194
|
-
) -> Page[ModelVersionResponse]:
|
195
|
-
"""Get model versions according to query filters.
|
196
|
-
|
197
|
-
This endpoint serves the purpose of allowing scoped filtering by model_id.
|
198
|
-
|
199
|
-
Args:
|
200
|
-
model_name_or_id: The name or ID of the model to list in.
|
201
|
-
model_version_filter_model: Filter model used for pagination, sorting,
|
202
|
-
filtering.
|
203
|
-
hydrate: Flag deciding whether to hydrate the output model(s)
|
204
|
-
by including metadata fields in the response.
|
205
|
-
auth_context: The authentication context.
|
206
|
-
|
207
|
-
Returns:
|
208
|
-
The model versions according to query filters.
|
209
|
-
"""
|
210
|
-
allowed_model_ids = get_allowed_resource_ids(
|
211
|
-
resource_type=ResourceType.MODEL
|
212
|
-
)
|
213
|
-
model_version_filter_model.configure_rbac(
|
214
|
-
authenticated_user_id=auth_context.user.id, model_id=allowed_model_ids
|
215
|
-
)
|
216
|
-
|
217
|
-
model_versions = zen_store().list_model_versions(
|
218
|
-
model_name_or_id=model_name_or_id,
|
219
|
-
model_version_filter_model=model_version_filter_model,
|
220
|
-
hydrate=hydrate,
|
221
|
-
)
|
222
|
-
return dehydrate_page(model_versions)
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for builds."""
|
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,16 +22,21 @@ from zenml.constants import API, PIPELINE_BUILDS, VERSION_1
|
|
21
22
|
from zenml.models import (
|
22
23
|
Page,
|
23
24
|
PipelineBuildFilter,
|
25
|
+
PipelineBuildRequest,
|
24
26
|
PipelineBuildResponse,
|
25
27
|
)
|
26
28
|
from zenml.zen_server.auth import AuthContext, authorize
|
27
29
|
from zenml.zen_server.exceptions import error_response
|
28
30
|
from zenml.zen_server.rbac.endpoint_utils import (
|
31
|
+
verify_permissions_and_create_entity,
|
29
32
|
verify_permissions_and_delete_entity,
|
30
33
|
verify_permissions_and_get_entity,
|
31
34
|
verify_permissions_and_list_entities,
|
32
35
|
)
|
33
36
|
from zenml.zen_server.rbac.models import ResourceType
|
37
|
+
from zenml.zen_server.routers.workspaces_endpoints import (
|
38
|
+
router as workspace_router,
|
39
|
+
)
|
34
40
|
from zenml.zen_server.utils import (
|
35
41
|
handle_exceptions,
|
36
42
|
make_dependable,
|
@@ -44,30 +50,79 @@ router = APIRouter(
|
|
44
50
|
)
|
45
51
|
|
46
52
|
|
53
|
+
@router.post(
|
54
|
+
"",
|
55
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
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
|
+
"/{workspace_name_or_id}" + PIPELINE_BUILDS,
|
61
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
62
|
+
deprecated=True,
|
63
|
+
tags=["builds"],
|
64
|
+
)
|
65
|
+
@handle_exceptions
|
66
|
+
def create_build(
|
67
|
+
build: PipelineBuildRequest,
|
68
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
69
|
+
_: AuthContext = Security(authorize),
|
70
|
+
) -> PipelineBuildResponse:
|
71
|
+
"""Creates a build, optionally in a specific workspace.
|
72
|
+
|
73
|
+
Args:
|
74
|
+
build: Build to create.
|
75
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
76
|
+
|
77
|
+
Returns:
|
78
|
+
The created build.
|
79
|
+
"""
|
80
|
+
if workspace_name_or_id:
|
81
|
+
workspace = zen_store().get_workspace(workspace_name_or_id)
|
82
|
+
build.workspace = workspace.id
|
83
|
+
|
84
|
+
return verify_permissions_and_create_entity(
|
85
|
+
request_model=build,
|
86
|
+
create_method=zen_store().create_build,
|
87
|
+
)
|
88
|
+
|
89
|
+
|
47
90
|
@router.get(
|
48
91
|
"",
|
49
|
-
response_model=Page[PipelineBuildResponse],
|
50
92
|
responses={401: error_response, 404: error_response, 422: error_response},
|
51
93
|
)
|
94
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
95
|
+
# and can be removed after the migration
|
96
|
+
@workspace_router.get(
|
97
|
+
"/{workspace_name_or_id}" + PIPELINE_BUILDS,
|
98
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
99
|
+
deprecated=True,
|
100
|
+
tags=["builds"],
|
101
|
+
)
|
52
102
|
@handle_exceptions
|
53
103
|
def list_builds(
|
54
104
|
build_filter_model: PipelineBuildFilter = Depends(
|
55
105
|
make_dependable(PipelineBuildFilter)
|
56
106
|
),
|
107
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
57
108
|
hydrate: bool = False,
|
58
109
|
_: AuthContext = Security(authorize),
|
59
110
|
) -> Page[PipelineBuildResponse]:
|
60
|
-
"""Gets a list of builds.
|
111
|
+
"""Gets a list of builds, optionally filtered by workspace.
|
61
112
|
|
62
113
|
Args:
|
63
114
|
build_filter_model: Filter model used for pagination, sorting,
|
64
115
|
filtering.
|
116
|
+
workspace_name_or_id: Optional name or ID of the workspace to filter by.
|
65
117
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
66
118
|
by including metadata fields in the response.
|
67
119
|
|
68
120
|
Returns:
|
69
|
-
List of build objects.
|
121
|
+
List of build objects matching the filter criteria.
|
70
122
|
"""
|
123
|
+
if workspace_name_or_id:
|
124
|
+
build_filter_model.workspace = workspace_name_or_id
|
125
|
+
|
71
126
|
return verify_permissions_and_list_entities(
|
72
127
|
filter_model=build_filter_model,
|
73
128
|
resource_type=ResourceType.PIPELINE_BUILD,
|
@@ -78,7 +133,6 @@ def list_builds(
|
|
78
133
|
|
79
134
|
@router.get(
|
80
135
|
"/{build_id}",
|
81
|
-
response_model=PipelineBuildResponse,
|
82
136
|
responses={401: error_response, 404: error_response, 422: error_response},
|
83
137
|
)
|
84
138
|
@handle_exceptions
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for deployments."""
|
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,16 +22,21 @@ from zenml.constants import API, PIPELINE_DEPLOYMENTS, VERSION_1
|
|
21
22
|
from zenml.models import (
|
22
23
|
Page,
|
23
24
|
PipelineDeploymentFilter,
|
25
|
+
PipelineDeploymentRequest,
|
24
26
|
PipelineDeploymentResponse,
|
25
27
|
)
|
26
28
|
from zenml.zen_server.auth import AuthContext, authorize
|
27
29
|
from zenml.zen_server.exceptions import error_response
|
28
30
|
from zenml.zen_server.rbac.endpoint_utils import (
|
31
|
+
verify_permissions_and_create_entity,
|
29
32
|
verify_permissions_and_delete_entity,
|
30
33
|
verify_permissions_and_get_entity,
|
31
34
|
verify_permissions_and_list_entities,
|
32
35
|
)
|
33
36
|
from zenml.zen_server.rbac.models import ResourceType
|
37
|
+
from zenml.zen_server.routers.workspaces_endpoints import (
|
38
|
+
router as workspace_router,
|
39
|
+
)
|
34
40
|
from zenml.zen_server.utils import (
|
35
41
|
handle_exceptions,
|
36
42
|
make_dependable,
|
@@ -46,30 +52,79 @@ router = APIRouter(
|
|
46
52
|
)
|
47
53
|
|
48
54
|
|
55
|
+
@router.post(
|
56
|
+
"",
|
57
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
58
|
+
)
|
59
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
60
|
+
# and can be removed after the migration
|
61
|
+
@workspace_router.post(
|
62
|
+
"/{workspace_name_or_id}" + PIPELINE_DEPLOYMENTS,
|
63
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
64
|
+
deprecated=True,
|
65
|
+
tags=["deployments"],
|
66
|
+
)
|
67
|
+
@handle_exceptions
|
68
|
+
def create_deployment(
|
69
|
+
deployment: PipelineDeploymentRequest,
|
70
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
71
|
+
_: AuthContext = Security(authorize),
|
72
|
+
) -> PipelineDeploymentResponse:
|
73
|
+
"""Creates a deployment.
|
74
|
+
|
75
|
+
Args:
|
76
|
+
deployment: Deployment to create.
|
77
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
78
|
+
|
79
|
+
Returns:
|
80
|
+
The created deployment.
|
81
|
+
"""
|
82
|
+
if workspace_name_or_id:
|
83
|
+
workspace = zen_store().get_workspace(workspace_name_or_id)
|
84
|
+
deployment.workspace = workspace.id
|
85
|
+
|
86
|
+
return verify_permissions_and_create_entity(
|
87
|
+
request_model=deployment,
|
88
|
+
create_method=zen_store().create_deployment,
|
89
|
+
)
|
90
|
+
|
91
|
+
|
49
92
|
@router.get(
|
50
93
|
"",
|
51
|
-
response_model=Page[PipelineDeploymentResponse],
|
52
94
|
responses={401: error_response, 404: error_response, 422: error_response},
|
53
95
|
)
|
96
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
97
|
+
# and can be removed after the migration
|
98
|
+
@workspace_router.get(
|
99
|
+
"/{workspace_name_or_id}" + PIPELINE_DEPLOYMENTS,
|
100
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
101
|
+
deprecated=True,
|
102
|
+
tags=["deployments"],
|
103
|
+
)
|
54
104
|
@handle_exceptions
|
55
105
|
def list_deployments(
|
56
106
|
deployment_filter_model: PipelineDeploymentFilter = Depends(
|
57
107
|
make_dependable(PipelineDeploymentFilter)
|
58
108
|
),
|
109
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
59
110
|
hydrate: bool = False,
|
60
111
|
_: AuthContext = Security(authorize),
|
61
112
|
) -> Page[PipelineDeploymentResponse]:
|
62
|
-
"""Gets a list of
|
113
|
+
"""Gets a list of deployments, optionally filtered by workspace.
|
63
114
|
|
64
115
|
Args:
|
65
116
|
deployment_filter_model: Filter model used for pagination, sorting,
|
66
117
|
filtering.
|
118
|
+
workspace_name_or_id: Optional name or ID of the workspace to filter by.
|
67
119
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
68
120
|
by including metadata fields in the response.
|
69
121
|
|
70
122
|
Returns:
|
71
|
-
List of deployment objects.
|
123
|
+
List of deployment objects matching the filter criteria.
|
72
124
|
"""
|
125
|
+
if workspace_name_or_id:
|
126
|
+
deployment_filter_model.workspace = workspace_name_or_id
|
127
|
+
|
73
128
|
return verify_permissions_and_list_entities(
|
74
129
|
filter_model=deployment_filter_model,
|
75
130
|
resource_type=ResourceType.PIPELINE_DEPLOYMENT,
|
@@ -80,7 +135,6 @@ def list_deployments(
|
|
80
135
|
|
81
136
|
@router.get(
|
82
137
|
"/{deployment_id}",
|
83
|
-
response_model=PipelineDeploymentResponse,
|
84
138
|
responses={401: error_response, 404: error_response, 422: error_response},
|
85
139
|
)
|
86
140
|
@handle_exceptions
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for pipelines."""
|
15
15
|
|
16
|
+
from typing import Optional, Union
|
16
17
|
from uuid import UUID
|
17
18
|
|
18
19
|
from fastapi import APIRouter, Depends, Security
|
@@ -26,6 +27,7 @@ from zenml.constants import (
|
|
26
27
|
from zenml.models import (
|
27
28
|
Page,
|
28
29
|
PipelineFilter,
|
30
|
+
PipelineRequest,
|
29
31
|
PipelineResponse,
|
30
32
|
PipelineRunFilter,
|
31
33
|
PipelineRunResponse,
|
@@ -33,14 +35,20 @@ from zenml.models import (
|
|
33
35
|
)
|
34
36
|
from zenml.zen_server.auth import AuthContext, authorize
|
35
37
|
from zenml.zen_server.exceptions import error_response
|
36
|
-
from zenml.zen_server.feature_gate.endpoint_utils import
|
38
|
+
from zenml.zen_server.feature_gate.endpoint_utils import (
|
39
|
+
report_decrement,
|
40
|
+
)
|
37
41
|
from zenml.zen_server.rbac.endpoint_utils import (
|
42
|
+
verify_permissions_and_create_entity,
|
38
43
|
verify_permissions_and_delete_entity,
|
39
44
|
verify_permissions_and_get_entity,
|
40
45
|
verify_permissions_and_list_entities,
|
41
46
|
verify_permissions_and_update_entity,
|
42
47
|
)
|
43
48
|
from zenml.zen_server.rbac.models import ResourceType
|
49
|
+
from zenml.zen_server.routers.workspaces_endpoints import (
|
50
|
+
router as workspace_router,
|
51
|
+
)
|
44
52
|
from zenml.zen_server.utils import (
|
45
53
|
handle_exceptions,
|
46
54
|
make_dependable,
|
@@ -55,29 +63,88 @@ router = APIRouter(
|
|
55
63
|
)
|
56
64
|
|
57
65
|
|
66
|
+
@router.post(
|
67
|
+
"",
|
68
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
69
|
+
)
|
70
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
71
|
+
# and can be removed after the migration
|
72
|
+
@workspace_router.post(
|
73
|
+
"/{workspace_name_or_id}" + PIPELINES,
|
74
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
75
|
+
deprecated=True,
|
76
|
+
tags=["pipelines"],
|
77
|
+
)
|
78
|
+
@handle_exceptions
|
79
|
+
def create_pipeline(
|
80
|
+
pipeline: PipelineRequest,
|
81
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
82
|
+
_: AuthContext = Security(authorize),
|
83
|
+
) -> PipelineResponse:
|
84
|
+
"""Creates a pipeline, optionally in a specific workspace.
|
85
|
+
|
86
|
+
Args:
|
87
|
+
pipeline: Pipeline to create.
|
88
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
89
|
+
|
90
|
+
Returns:
|
91
|
+
The created pipeline.
|
92
|
+
"""
|
93
|
+
if workspace_name_or_id:
|
94
|
+
workspace = zen_store().get_workspace(workspace_name_or_id)
|
95
|
+
pipeline.workspace = workspace.id
|
96
|
+
|
97
|
+
# We limit pipeline namespaces, not pipeline versions
|
98
|
+
skip_entitlements = (
|
99
|
+
zen_store().count_pipelines(
|
100
|
+
PipelineFilter(name=pipeline.name, workspace=pipeline.workspace)
|
101
|
+
)
|
102
|
+
> 0
|
103
|
+
)
|
104
|
+
|
105
|
+
return verify_permissions_and_create_entity(
|
106
|
+
request_model=pipeline,
|
107
|
+
create_method=zen_store().create_pipeline,
|
108
|
+
skip_entitlements=skip_entitlements,
|
109
|
+
)
|
110
|
+
|
111
|
+
|
58
112
|
@router.get(
|
59
113
|
"",
|
60
114
|
responses={401: error_response, 404: error_response, 422: error_response},
|
61
115
|
)
|
116
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
117
|
+
# and can be removed after the migration
|
118
|
+
@workspace_router.get(
|
119
|
+
"/{workspace_name_or_id}" + PIPELINES,
|
120
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
121
|
+
deprecated=True,
|
122
|
+
tags=["pipelines"],
|
123
|
+
)
|
62
124
|
@handle_exceptions
|
63
125
|
def list_pipelines(
|
64
126
|
pipeline_filter_model: PipelineFilter = Depends(
|
65
127
|
make_dependable(PipelineFilter)
|
66
128
|
),
|
129
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
67
130
|
hydrate: bool = False,
|
68
131
|
_: AuthContext = Security(authorize),
|
69
132
|
) -> Page[PipelineResponse]:
|
70
|
-
"""Gets a list of pipelines.
|
133
|
+
"""Gets a list of pipelines, optionally filtered by workspace.
|
71
134
|
|
72
135
|
Args:
|
73
136
|
pipeline_filter_model: Filter model used for pagination, sorting,
|
74
137
|
filtering.
|
138
|
+
workspace_name_or_id: Optional name or ID of the workspace to filter by.
|
75
139
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
76
140
|
by including metadata fields in the response.
|
77
141
|
|
78
142
|
Returns:
|
79
|
-
List of pipeline objects.
|
143
|
+
List of pipeline objects matching the filter criteria.
|
80
144
|
"""
|
145
|
+
if workspace_name_or_id:
|
146
|
+
pipeline_filter_model.workspace = workspace_name_or_id
|
147
|
+
|
81
148
|
return verify_permissions_and_list_entities(
|
82
149
|
filter_model=pipeline_filter_model,
|
83
150
|
resource_type=ResourceType.PIPELINE,
|
@@ -160,7 +227,9 @@ def delete_pipeline(
|
|
160
227
|
|
161
228
|
should_decrement = (
|
162
229
|
ResourceType.PIPELINE in server_config().reportable_resources
|
163
|
-
and zen_store().count_pipelines(
|
230
|
+
and zen_store().count_pipelines(
|
231
|
+
PipelineFilter(name=pipeline.name, workspace=pipeline.workspace.id)
|
232
|
+
)
|
164
233
|
== 0
|
165
234
|
)
|
166
235
|
if should_decrement:
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2025. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Endpoint definitions for run metadata."""
|
15
|
+
|
16
|
+
from typing import Any, List, Optional, Union
|
17
|
+
from uuid import UUID
|
18
|
+
|
19
|
+
from fastapi import APIRouter, Security
|
20
|
+
|
21
|
+
from zenml.constants import API, RUN_METADATA, VERSION_1
|
22
|
+
from zenml.enums import MetadataResourceTypes
|
23
|
+
from zenml.models import RunMetadataRequest
|
24
|
+
from zenml.zen_server.auth import AuthContext, authorize
|
25
|
+
from zenml.zen_server.exceptions import error_response
|
26
|
+
from zenml.zen_server.rbac.models import Action
|
27
|
+
from zenml.zen_server.rbac.utils import (
|
28
|
+
batch_verify_permissions_for_models,
|
29
|
+
verify_permission_for_model,
|
30
|
+
)
|
31
|
+
from zenml.zen_server.routers.workspaces_endpoints import (
|
32
|
+
router as workspace_router,
|
33
|
+
)
|
34
|
+
from zenml.zen_server.utils import handle_exceptions, zen_store
|
35
|
+
|
36
|
+
router = APIRouter(
|
37
|
+
prefix=API + VERSION_1 + RUN_METADATA,
|
38
|
+
tags=["run_metadata"],
|
39
|
+
responses={401: error_response, 403: error_response},
|
40
|
+
)
|
41
|
+
|
42
|
+
|
43
|
+
@router.post(
|
44
|
+
"",
|
45
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
46
|
+
)
|
47
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
48
|
+
# and can be removed after the migration
|
49
|
+
@workspace_router.post(
|
50
|
+
"/{workspace_name_or_id}" + RUN_METADATA,
|
51
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
52
|
+
deprecated=True,
|
53
|
+
tags=["run_metadata"],
|
54
|
+
)
|
55
|
+
@handle_exceptions
|
56
|
+
def create_run_metadata(
|
57
|
+
run_metadata: RunMetadataRequest,
|
58
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
59
|
+
auth_context: AuthContext = Security(authorize),
|
60
|
+
) -> None:
|
61
|
+
"""Creates run metadata.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
run_metadata: The run metadata to create.
|
65
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
66
|
+
auth_context: Authentication context.
|
67
|
+
|
68
|
+
Raises:
|
69
|
+
RuntimeError: If the resource type is not supported.
|
70
|
+
"""
|
71
|
+
if workspace_name_or_id:
|
72
|
+
workspace = zen_store().get_workspace(workspace_name_or_id)
|
73
|
+
run_metadata.workspace = workspace.id
|
74
|
+
|
75
|
+
run_metadata.user = auth_context.user.id
|
76
|
+
|
77
|
+
verify_models: List[Any] = []
|
78
|
+
for resource in run_metadata.resources:
|
79
|
+
if resource.type == MetadataResourceTypes.PIPELINE_RUN:
|
80
|
+
verify_models.append(zen_store().get_run(resource.id))
|
81
|
+
elif resource.type == MetadataResourceTypes.STEP_RUN:
|
82
|
+
verify_models.append(zen_store().get_run_step(resource.id))
|
83
|
+
elif resource.type == MetadataResourceTypes.ARTIFACT_VERSION:
|
84
|
+
verify_models.append(zen_store().get_artifact_version(resource.id))
|
85
|
+
elif resource.type == MetadataResourceTypes.MODEL_VERSION:
|
86
|
+
verify_models.append(zen_store().get_model_version(resource.id))
|
87
|
+
elif resource.type == MetadataResourceTypes.SCHEDULE:
|
88
|
+
verify_models.append(zen_store().get_schedule(resource.id))
|
89
|
+
else:
|
90
|
+
raise RuntimeError(f"Unknown resource type: {resource.type}")
|
91
|
+
|
92
|
+
batch_verify_permissions_for_models(
|
93
|
+
models=verify_models,
|
94
|
+
action=Action.UPDATE,
|
95
|
+
)
|
96
|
+
|
97
|
+
verify_permission_for_model(model=run_metadata, action=Action.CREATE)
|
98
|
+
|
99
|
+
zen_store().create_run_metadata(run_metadata)
|