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
@@ -66,7 +66,10 @@ from zenml.zen_server.auth import (
|
|
66
66
|
from zenml.zen_server.exceptions import error_response
|
67
67
|
from zenml.zen_server.rate_limit import rate_limit_requests
|
68
68
|
from zenml.zen_server.rbac.models import Action, ResourceType
|
69
|
-
from zenml.zen_server.rbac.utils import
|
69
|
+
from zenml.zen_server.rbac.utils import (
|
70
|
+
verify_permission,
|
71
|
+
verify_permission_for_model,
|
72
|
+
)
|
70
73
|
from zenml.zen_server.utils import (
|
71
74
|
get_ip_location,
|
72
75
|
handle_exceptions,
|
@@ -544,10 +547,6 @@ def api_token(
|
|
544
547
|
response=None,
|
545
548
|
).access_token
|
546
549
|
|
547
|
-
verify_permission(
|
548
|
-
resource_type=ResourceType.PIPELINE_RUN, action=Action.CREATE
|
549
|
-
)
|
550
|
-
|
551
550
|
schedule_id = schedule_id or token.schedule_id
|
552
551
|
pipeline_run_id = pipeline_run_id or token.pipeline_run_id
|
553
552
|
step_run_id = step_run_id or token.step_run_id
|
@@ -583,15 +582,18 @@ def api_token(
|
|
583
582
|
f"step run {token.step_run_id}."
|
584
583
|
)
|
585
584
|
|
585
|
+
workspace_id: Optional[UUID] = None
|
586
|
+
|
586
587
|
if schedule_id:
|
587
588
|
# The schedule must exist
|
588
589
|
try:
|
589
|
-
schedule = zen_store().get_schedule(schedule_id, hydrate=
|
590
|
+
schedule = zen_store().get_schedule(schedule_id, hydrate=True)
|
590
591
|
except KeyError:
|
591
592
|
raise ValueError(
|
592
593
|
f"Schedule {schedule_id} does not exist and API tokens cannot "
|
593
594
|
"be generated for non-existent schedules for security reasons."
|
594
595
|
)
|
596
|
+
workspace_id = schedule.workspace.id
|
595
597
|
|
596
598
|
if not schedule.active:
|
597
599
|
raise ValueError(
|
@@ -602,7 +604,7 @@ def api_token(
|
|
602
604
|
if pipeline_run_id:
|
603
605
|
# The pipeline run must exist and the run must not be concluded
|
604
606
|
try:
|
605
|
-
pipeline_run = zen_store().get_run(pipeline_run_id, hydrate=
|
607
|
+
pipeline_run = zen_store().get_run(pipeline_run_id, hydrate=True)
|
606
608
|
except KeyError:
|
607
609
|
raise ValueError(
|
608
610
|
f"Pipeline run {pipeline_run_id} does not exist and API tokens "
|
@@ -610,6 +612,10 @@ def api_token(
|
|
610
612
|
"security reasons."
|
611
613
|
)
|
612
614
|
|
615
|
+
verify_permission_for_model(model=pipeline_run, action=Action.READ)
|
616
|
+
|
617
|
+
workspace_id = pipeline_run.workspace.id
|
618
|
+
|
613
619
|
if pipeline_run.status.is_finished:
|
614
620
|
raise ValueError(
|
615
621
|
f"The execution of pipeline run {pipeline_run_id} has already "
|
@@ -627,6 +633,8 @@ def api_token(
|
|
627
633
|
"be generated for non-existent step runs for security reasons."
|
628
634
|
)
|
629
635
|
|
636
|
+
workspace_id = step_run.workspace.id
|
637
|
+
|
630
638
|
if step_run.status.is_finished:
|
631
639
|
raise ValueError(
|
632
640
|
f"The execution of step run {step_run_id} has already "
|
@@ -634,6 +642,13 @@ def api_token(
|
|
634
642
|
"for security reasons."
|
635
643
|
)
|
636
644
|
|
645
|
+
assert workspace_id is not None
|
646
|
+
verify_permission(
|
647
|
+
resource_type=ResourceType.PIPELINE_RUN,
|
648
|
+
action=Action.CREATE,
|
649
|
+
workspace_id=workspace_id,
|
650
|
+
)
|
651
|
+
|
637
652
|
return generate_access_token(
|
638
653
|
user_id=token.user_id,
|
639
654
|
# Keep the original API key and device token scopes
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for code repositories."""
|
15
15
|
|
16
|
+
from typing import Optional, Union
|
16
17
|
from uuid import UUID
|
17
18
|
|
18
19
|
from fastapi import APIRouter, Depends, Security
|
@@ -20,6 +21,7 @@ from fastapi import APIRouter, Depends, Security
|
|
20
21
|
from zenml.constants import API, CODE_REPOSITORIES, VERSION_1
|
21
22
|
from zenml.models import (
|
22
23
|
CodeRepositoryFilter,
|
24
|
+
CodeRepositoryRequest,
|
23
25
|
CodeRepositoryResponse,
|
24
26
|
CodeRepositoryUpdate,
|
25
27
|
Page,
|
@@ -27,12 +29,16 @@ from zenml.models import (
|
|
27
29
|
from zenml.zen_server.auth import AuthContext, authorize
|
28
30
|
from zenml.zen_server.exceptions import error_response
|
29
31
|
from zenml.zen_server.rbac.endpoint_utils import (
|
32
|
+
verify_permissions_and_create_entity,
|
30
33
|
verify_permissions_and_delete_entity,
|
31
34
|
verify_permissions_and_get_entity,
|
32
35
|
verify_permissions_and_list_entities,
|
33
36
|
verify_permissions_and_update_entity,
|
34
37
|
)
|
35
38
|
from zenml.zen_server.rbac.models import ResourceType
|
39
|
+
from zenml.zen_server.routers.workspaces_endpoints import (
|
40
|
+
router as workspace_router,
|
41
|
+
)
|
36
42
|
from zenml.zen_server.utils import (
|
37
43
|
handle_exceptions,
|
38
44
|
make_dependable,
|
@@ -46,16 +52,61 @@ 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}" + CODE_REPOSITORIES,
|
63
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
64
|
+
deprecated=True,
|
65
|
+
tags=["code_repositories"],
|
66
|
+
)
|
67
|
+
@handle_exceptions
|
68
|
+
def create_code_repository(
|
69
|
+
code_repository: CodeRepositoryRequest,
|
70
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
71
|
+
_: AuthContext = Security(authorize),
|
72
|
+
) -> CodeRepositoryResponse:
|
73
|
+
"""Creates a code repository.
|
74
|
+
|
75
|
+
Args:
|
76
|
+
code_repository: Code repository to create.
|
77
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
78
|
+
|
79
|
+
Returns:
|
80
|
+
The created code repository.
|
81
|
+
"""
|
82
|
+
if workspace_name_or_id:
|
83
|
+
workspace = zen_store().get_workspace(workspace_name_or_id)
|
84
|
+
code_repository.workspace = workspace.id
|
85
|
+
|
86
|
+
return verify_permissions_and_create_entity(
|
87
|
+
request_model=code_repository,
|
88
|
+
create_method=zen_store().create_code_repository,
|
89
|
+
)
|
90
|
+
|
91
|
+
|
49
92
|
@router.get(
|
50
93
|
"",
|
51
|
-
response_model=Page[CodeRepositoryResponse],
|
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}" + CODE_REPOSITORIES,
|
100
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
101
|
+
deprecated=True,
|
102
|
+
tags=["code_repositories"],
|
103
|
+
)
|
54
104
|
@handle_exceptions
|
55
105
|
def list_code_repositories(
|
56
106
|
filter_model: CodeRepositoryFilter = Depends(
|
57
107
|
make_dependable(CodeRepositoryFilter)
|
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[CodeRepositoryResponse]:
|
@@ -64,12 +115,16 @@ def list_code_repositories(
|
|
64
115
|
Args:
|
65
116
|
filter_model: Filter model used for pagination, sorting,
|
66
117
|
filtering.
|
118
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
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
123
|
Page of code repository objects.
|
72
124
|
"""
|
125
|
+
if workspace_name_or_id:
|
126
|
+
filter_model.workspace = workspace_name_or_id
|
127
|
+
|
73
128
|
return verify_permissions_and_list_entities(
|
74
129
|
filter_model=filter_model,
|
75
130
|
resource_type=ResourceType.CODE_REPOSITORY,
|
@@ -80,7 +135,6 @@ def list_code_repositories(
|
|
80
135
|
|
81
136
|
@router.get(
|
82
137
|
"/{code_repository_id}",
|
83
|
-
response_model=CodeRepositoryResponse,
|
84
138
|
responses={401: error_response, 404: error_response, 422: error_response},
|
85
139
|
)
|
86
140
|
@handle_exceptions
|
@@ -108,7 +162,6 @@ def get_code_repository(
|
|
108
162
|
|
109
163
|
@router.put(
|
110
164
|
"/{code_repository_id}",
|
111
|
-
response_model=CodeRepositoryResponse,
|
112
165
|
responses={401: error_response, 404: error_response, 422: error_response},
|
113
166
|
)
|
114
167
|
@handle_exceptions
|
@@ -54,7 +54,6 @@ router = APIRouter(
|
|
54
54
|
|
55
55
|
@router.get(
|
56
56
|
"",
|
57
|
-
response_model=Page[OAuthDeviceResponse],
|
58
57
|
responses={401: error_response, 404: error_response, 422: error_response},
|
59
58
|
)
|
60
59
|
@handle_exceptions
|
@@ -85,7 +84,6 @@ def list_authorized_devices(
|
|
85
84
|
|
86
85
|
@router.get(
|
87
86
|
"/{device_id}",
|
88
|
-
response_model=OAuthDeviceResponse,
|
89
87
|
responses={401: error_response, 404: error_response, 422: error_response},
|
90
88
|
)
|
91
89
|
@handle_exceptions
|
@@ -136,7 +134,6 @@ def get_authorization_device(
|
|
136
134
|
|
137
135
|
@router.put(
|
138
136
|
"/{device_id}",
|
139
|
-
response_model=OAuthDeviceResponse,
|
140
137
|
responses={401: error_response, 404: error_response, 422: error_response},
|
141
138
|
)
|
142
139
|
@handle_exceptions
|
@@ -173,7 +170,6 @@ def update_authorized_device(
|
|
173
170
|
|
174
171
|
@router.put(
|
175
172
|
"/{device_id}" + DEVICE_VERIFY,
|
176
|
-
response_model=OAuthDeviceResponse,
|
177
173
|
responses={401: error_response, 404: error_response, 422: error_response},
|
178
174
|
)
|
179
175
|
@handle_exceptions
|
@@ -57,7 +57,6 @@ event_source_router = APIRouter(
|
|
57
57
|
|
58
58
|
@event_source_router.get(
|
59
59
|
"",
|
60
|
-
response_model=Page[EventSourceResponse],
|
61
60
|
responses={401: error_response, 404: error_response, 422: error_response},
|
62
61
|
)
|
63
62
|
@handle_exceptions
|
@@ -132,7 +131,6 @@ def list_event_sources(
|
|
132
131
|
|
133
132
|
@event_source_router.get(
|
134
133
|
"/{event_source_id}",
|
135
|
-
response_model=EventSourceResponse,
|
136
134
|
responses={401: error_response, 404: error_response, 422: error_response},
|
137
135
|
)
|
138
136
|
@handle_exceptions
|
@@ -185,7 +183,6 @@ def get_event_source(
|
|
185
183
|
|
186
184
|
@event_source_router.post(
|
187
185
|
"",
|
188
|
-
response_model=EventSourceResponse,
|
189
186
|
responses={401: error_response, 409: error_response, 422: error_response},
|
190
187
|
)
|
191
188
|
@handle_exceptions
|
@@ -222,14 +219,12 @@ def create_event_source(
|
|
222
219
|
|
223
220
|
return verify_permissions_and_create_entity(
|
224
221
|
request_model=event_source,
|
225
|
-
resource_type=ResourceType.EVENT_SOURCE,
|
226
222
|
create_method=event_source_handler.create_event_source,
|
227
223
|
)
|
228
224
|
|
229
225
|
|
230
226
|
@event_source_router.put(
|
231
227
|
"/{event_source_id}",
|
232
|
-
response_model=EventSourceResponse,
|
233
228
|
responses={401: error_response, 404: error_response, 422: error_response},
|
234
229
|
)
|
235
230
|
@handle_exceptions
|
@@ -51,7 +51,6 @@ router = APIRouter(
|
|
51
51
|
|
52
52
|
@router.get(
|
53
53
|
"",
|
54
|
-
response_model=Page[FlavorResponse],
|
55
54
|
responses={401: error_response, 404: error_response, 422: error_response},
|
56
55
|
)
|
57
56
|
@handle_exceptions
|
@@ -81,7 +80,6 @@ def list_flavors(
|
|
81
80
|
|
82
81
|
@router.get(
|
83
82
|
"/{flavor_id}",
|
84
|
-
response_model=FlavorResponse,
|
85
83
|
responses={401: error_response, 404: error_response, 422: error_response},
|
86
84
|
)
|
87
85
|
@handle_exceptions
|
@@ -107,7 +105,6 @@ def get_flavor(
|
|
107
105
|
|
108
106
|
@router.post(
|
109
107
|
"",
|
110
|
-
response_model=FlavorResponse,
|
111
108
|
responses={401: error_response, 409: error_response, 422: error_response},
|
112
109
|
)
|
113
110
|
@handle_exceptions
|
@@ -125,14 +122,12 @@ def create_flavor(
|
|
125
122
|
"""
|
126
123
|
return verify_permissions_and_create_entity(
|
127
124
|
request_model=flavor,
|
128
|
-
resource_type=ResourceType.FLAVOR,
|
129
125
|
create_method=zen_store().create_flavor,
|
130
126
|
)
|
131
127
|
|
132
128
|
|
133
129
|
@router.put(
|
134
130
|
"/{flavor_id}",
|
135
|
-
response_model=FlavorResponse,
|
136
131
|
responses={401: error_response, 409: error_response, 422: error_response},
|
137
132
|
)
|
138
133
|
@handle_exceptions
|
@@ -13,7 +13,7 @@
|
|
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
|
@@ -24,6 +24,7 @@ from zenml.constants import (
|
|
24
24
|
MODEL_VERSION_ARTIFACTS,
|
25
25
|
MODEL_VERSION_PIPELINE_RUNS,
|
26
26
|
MODEL_VERSIONS,
|
27
|
+
MODELS,
|
27
28
|
RUNS,
|
28
29
|
VERSION_1,
|
29
30
|
)
|
@@ -35,22 +36,33 @@ from zenml.models import (
|
|
35
36
|
ModelVersionPipelineRunFilter,
|
36
37
|
ModelVersionPipelineRunRequest,
|
37
38
|
ModelVersionPipelineRunResponse,
|
39
|
+
ModelVersionRequest,
|
38
40
|
ModelVersionResponse,
|
39
41
|
ModelVersionUpdate,
|
40
42
|
)
|
41
43
|
from zenml.models.v2.base.page import Page
|
42
44
|
from zenml.zen_server.auth import AuthContext, authorize
|
43
45
|
from zenml.zen_server.exceptions import error_response
|
44
|
-
from zenml.zen_server.rbac.
|
46
|
+
from zenml.zen_server.rbac.endpoint_utils import (
|
47
|
+
verify_permissions_and_create_entity,
|
48
|
+
verify_permissions_and_delete_entity,
|
49
|
+
)
|
50
|
+
from zenml.zen_server.rbac.models import Action
|
45
51
|
from zenml.zen_server.rbac.utils import (
|
46
52
|
dehydrate_page,
|
47
53
|
dehydrate_response_model,
|
48
|
-
get_allowed_resource_ids,
|
49
54
|
verify_permission_for_model,
|
50
55
|
)
|
56
|
+
from zenml.zen_server.routers.models_endpoints import (
|
57
|
+
router as model_router,
|
58
|
+
)
|
59
|
+
from zenml.zen_server.routers.workspaces_endpoints import (
|
60
|
+
router as workspace_router,
|
61
|
+
)
|
51
62
|
from zenml.zen_server.utils import (
|
52
63
|
handle_exceptions,
|
53
64
|
make_dependable,
|
65
|
+
set_filter_workspace_scope,
|
54
66
|
zen_store,
|
55
67
|
)
|
56
68
|
|
@@ -66,9 +78,54 @@ router = APIRouter(
|
|
66
78
|
)
|
67
79
|
|
68
80
|
|
81
|
+
@router.post(
|
82
|
+
"",
|
83
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
84
|
+
)
|
85
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
86
|
+
# and can be removed after the migration
|
87
|
+
@workspace_router.post(
|
88
|
+
"/{workspace_name_or_id}" + MODELS + "/{model_id}" + MODEL_VERSIONS,
|
89
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
90
|
+
deprecated=True,
|
91
|
+
tags=["model_versions"],
|
92
|
+
)
|
93
|
+
@handle_exceptions
|
94
|
+
def create_model_version(
|
95
|
+
model_version: ModelVersionRequest,
|
96
|
+
model_id: Optional[UUID] = None,
|
97
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
98
|
+
_: AuthContext = Security(authorize),
|
99
|
+
) -> ModelVersionResponse:
|
100
|
+
"""Creates a model version.
|
101
|
+
|
102
|
+
Args:
|
103
|
+
model_version: Model version to create.
|
104
|
+
model_id: Optional ID of the model.
|
105
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
106
|
+
|
107
|
+
Returns:
|
108
|
+
The created model version.
|
109
|
+
"""
|
110
|
+
if workspace_name_or_id:
|
111
|
+
workspace = zen_store().get_workspace(workspace_name_or_id)
|
112
|
+
model_version.workspace = workspace.id
|
113
|
+
|
114
|
+
if model_id:
|
115
|
+
model_version.model = model_id
|
116
|
+
|
117
|
+
return verify_permissions_and_create_entity(
|
118
|
+
request_model=model_version,
|
119
|
+
create_method=zen_store().create_model_version,
|
120
|
+
)
|
121
|
+
|
122
|
+
|
123
|
+
@model_router.get(
|
124
|
+
"/{model_name_or_id}" + MODEL_VERSIONS,
|
125
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
126
|
+
)
|
69
127
|
@router.get(
|
70
128
|
"",
|
71
|
-
response_model=Page[ModelVersionResponse],
|
72
129
|
responses={401: error_response, 404: error_response, 422: error_response},
|
73
130
|
)
|
74
131
|
@handle_exceptions
|
@@ -76,6 +133,7 @@ def list_model_versions(
|
|
76
133
|
model_version_filter_model: ModelVersionFilter = Depends(
|
77
134
|
make_dependable(ModelVersionFilter)
|
78
135
|
),
|
136
|
+
model_name_or_id: Optional[Union[str, UUID]] = None,
|
79
137
|
hydrate: bool = False,
|
80
138
|
auth_context: AuthContext = Security(authorize),
|
81
139
|
) -> Page[ModelVersionResponse]:
|
@@ -84,19 +142,38 @@ def list_model_versions(
|
|
84
142
|
Args:
|
85
143
|
model_version_filter_model: Filter model used for pagination, sorting,
|
86
144
|
filtering.
|
145
|
+
model_name_or_id: Optional name or ID of the model.
|
87
146
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
88
147
|
by including metadata fields in the response.
|
89
148
|
auth_context: The authentication context.
|
90
149
|
|
91
150
|
Returns:
|
92
151
|
The model versions according to query filters.
|
152
|
+
|
153
|
+
Raises:
|
154
|
+
ValueError: If the model is missing from the filter.
|
93
155
|
"""
|
94
|
-
|
95
|
-
|
156
|
+
if model_name_or_id:
|
157
|
+
model_version_filter_model.model = model_name_or_id
|
158
|
+
|
159
|
+
if not model_version_filter_model.model:
|
160
|
+
raise ValueError("Model missing from the filter")
|
161
|
+
|
162
|
+
# A workspace scoped request must always be scoped to a specific
|
163
|
+
# workspace. This is required for the RBAC check to work.
|
164
|
+
set_filter_workspace_scope(model_version_filter_model)
|
165
|
+
assert isinstance(model_version_filter_model.workspace, UUID)
|
166
|
+
|
167
|
+
model = zen_store().get_model_by_name_or_id(
|
168
|
+
model_version_filter_model.model,
|
169
|
+
workspace=model_version_filter_model.workspace,
|
96
170
|
)
|
171
|
+
|
172
|
+
# Check read permissions on the model
|
173
|
+
verify_permission_for_model(model, action=Action.READ)
|
174
|
+
|
97
175
|
model_version_filter_model.configure_rbac(
|
98
|
-
authenticated_user_id=auth_context.user.id
|
99
|
-
model_id=allowed_model_ids,
|
176
|
+
authenticated_user_id=auth_context.user.id
|
100
177
|
)
|
101
178
|
|
102
179
|
model_versions = zen_store().list_model_versions(
|
@@ -108,7 +185,6 @@ def list_model_versions(
|
|
108
185
|
|
109
186
|
@router.get(
|
110
187
|
"/{model_version_id}",
|
111
|
-
response_model=ModelVersionResponse,
|
112
188
|
responses={401: error_response, 404: error_response, 422: error_response},
|
113
189
|
)
|
114
190
|
@handle_exceptions
|
@@ -137,7 +213,6 @@ def get_model_version(
|
|
137
213
|
|
138
214
|
@router.put(
|
139
215
|
"/{model_version_id}",
|
140
|
-
response_model=ModelVersionResponse,
|
141
216
|
responses={401: error_response, 404: error_response, 422: error_response},
|
142
217
|
)
|
143
218
|
@handle_exceptions
|
@@ -184,9 +259,11 @@ def delete_model_version(
|
|
184
259
|
Args:
|
185
260
|
model_version_id: The name or ID of the model version to delete.
|
186
261
|
"""
|
187
|
-
|
188
|
-
|
189
|
-
|
262
|
+
verify_permissions_and_delete_entity(
|
263
|
+
id=model_version_id,
|
264
|
+
get_method=zen_store().get_model_version,
|
265
|
+
delete_method=zen_store().delete_model_version,
|
266
|
+
)
|
190
267
|
|
191
268
|
|
192
269
|
##########################
|
@@ -220,17 +297,18 @@ def create_model_version_artifact_link(
|
|
220
297
|
model_version = zen_store().get_model_version(
|
221
298
|
model_version_artifact_link.model_version
|
222
299
|
)
|
223
|
-
verify_permission_for_model(model_version, action=Action.UPDATE)
|
224
300
|
|
225
|
-
|
226
|
-
model_version_artifact_link
|
301
|
+
return verify_permissions_and_create_entity(
|
302
|
+
request_model=model_version_artifact_link,
|
303
|
+
create_method=zen_store().create_model_version_artifact_link,
|
304
|
+
# Check for UPDATE permissions on the model version instead of the
|
305
|
+
# model version artifact link
|
306
|
+
surrogate_models=[model_version],
|
227
307
|
)
|
228
|
-
return mv
|
229
308
|
|
230
309
|
|
231
310
|
@model_version_artifacts_router.get(
|
232
311
|
"",
|
233
|
-
response_model=Page[ModelVersionArtifactResponse],
|
234
312
|
responses={401: error_response, 404: error_response, 422: error_response},
|
235
313
|
)
|
236
314
|
@handle_exceptions
|
@@ -342,17 +420,18 @@ def create_model_version_pipeline_run_link(
|
|
342
420
|
model_version = zen_store().get_model_version(
|
343
421
|
model_version_pipeline_run_link.model_version, hydrate=False
|
344
422
|
)
|
345
|
-
verify_permission_for_model(model_version, action=Action.UPDATE)
|
346
423
|
|
347
|
-
|
348
|
-
model_version_pipeline_run_link
|
424
|
+
return verify_permissions_and_create_entity(
|
425
|
+
request_model=model_version_pipeline_run_link,
|
426
|
+
create_method=zen_store().create_model_version_pipeline_run_link,
|
427
|
+
# Check for UPDATE permissions on the model version instead of the
|
428
|
+
# model version pipeline run link
|
429
|
+
surrogate_models=[model_version],
|
349
430
|
)
|
350
|
-
return mv
|
351
431
|
|
352
432
|
|
353
433
|
@model_version_pipeline_runs_router.get(
|
354
434
|
"",
|
355
|
-
response_model=Page[ModelVersionPipelineRunResponse],
|
356
435
|
responses={401: error_response, 404: error_response, 422: error_response},
|
357
436
|
)
|
358
437
|
@handle_exceptions
|