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,12 +13,19 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for stacks."""
|
15
15
|
|
16
|
+
from typing import Optional, Union
|
16
17
|
from uuid import UUID
|
17
18
|
|
18
19
|
from fastapi import APIRouter, Depends, Security
|
19
20
|
|
20
21
|
from zenml.constants import API, STACKS, VERSION_1
|
21
|
-
from zenml.models import
|
22
|
+
from zenml.models import (
|
23
|
+
Page,
|
24
|
+
StackFilter,
|
25
|
+
StackRequest,
|
26
|
+
StackResponse,
|
27
|
+
StackUpdate,
|
28
|
+
)
|
22
29
|
from zenml.zen_server.auth import AuthContext, authorize
|
23
30
|
from zenml.zen_server.exceptions import error_response
|
24
31
|
from zenml.zen_server.rbac.endpoint_utils import (
|
@@ -28,7 +35,14 @@ from zenml.zen_server.rbac.endpoint_utils import (
|
|
28
35
|
verify_permissions_and_update_entity,
|
29
36
|
)
|
30
37
|
from zenml.zen_server.rbac.models import Action, ResourceType
|
31
|
-
from zenml.zen_server.rbac.utils import
|
38
|
+
from zenml.zen_server.rbac.utils import (
|
39
|
+
batch_verify_permissions_for_models,
|
40
|
+
verify_permission,
|
41
|
+
verify_permission_for_model,
|
42
|
+
)
|
43
|
+
from zenml.zen_server.routers.workspaces_endpoints import (
|
44
|
+
router as workspace_router,
|
45
|
+
)
|
32
46
|
from zenml.zen_server.utils import (
|
33
47
|
handle_exceptions,
|
34
48
|
make_dependable,
|
@@ -42,27 +56,106 @@ router = APIRouter(
|
|
42
56
|
)
|
43
57
|
|
44
58
|
|
59
|
+
@router.post(
|
60
|
+
"",
|
61
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
62
|
+
)
|
63
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
64
|
+
# and can be removed after the migration
|
65
|
+
@workspace_router.post(
|
66
|
+
"/{workspace_name_or_id}" + STACKS,
|
67
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
68
|
+
deprecated=True,
|
69
|
+
tags=["stacks"],
|
70
|
+
)
|
71
|
+
@handle_exceptions
|
72
|
+
def create_stack(
|
73
|
+
stack: StackRequest,
|
74
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
75
|
+
auth_context: AuthContext = Security(authorize),
|
76
|
+
) -> StackResponse:
|
77
|
+
"""Creates a stack, optionally in a specific workspace.
|
78
|
+
|
79
|
+
Args:
|
80
|
+
stack: Stack to register.
|
81
|
+
workspace_name_or_id: Optional name or ID of the workspace.
|
82
|
+
auth_context: Authentication context.
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
The created stack.
|
86
|
+
"""
|
87
|
+
# Check the service connector creation
|
88
|
+
is_connector_create_needed = False
|
89
|
+
for connector_id_or_info in stack.service_connectors:
|
90
|
+
if isinstance(connector_id_or_info, UUID):
|
91
|
+
service_connector = zen_store().get_service_connector(
|
92
|
+
connector_id_or_info, hydrate=False
|
93
|
+
)
|
94
|
+
verify_permission_for_model(
|
95
|
+
model=service_connector, action=Action.READ
|
96
|
+
)
|
97
|
+
else:
|
98
|
+
is_connector_create_needed = True
|
99
|
+
|
100
|
+
# Check the component creation
|
101
|
+
if is_connector_create_needed:
|
102
|
+
verify_permission(
|
103
|
+
resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
|
104
|
+
)
|
105
|
+
is_component_create_needed = False
|
106
|
+
for components in stack.components.values():
|
107
|
+
for component_id_or_info in components:
|
108
|
+
if isinstance(component_id_or_info, UUID):
|
109
|
+
component = zen_store().get_stack_component(
|
110
|
+
component_id_or_info, hydrate=False
|
111
|
+
)
|
112
|
+
verify_permission_for_model(
|
113
|
+
model=component, action=Action.READ
|
114
|
+
)
|
115
|
+
else:
|
116
|
+
is_component_create_needed = True
|
117
|
+
if is_component_create_needed:
|
118
|
+
verify_permission(
|
119
|
+
resource_type=ResourceType.STACK_COMPONENT,
|
120
|
+
action=Action.CREATE,
|
121
|
+
)
|
122
|
+
|
123
|
+
# Check the stack creation
|
124
|
+
verify_permission_for_model(model=stack, action=Action.CREATE)
|
125
|
+
|
126
|
+
return zen_store().create_stack(stack)
|
127
|
+
|
128
|
+
|
45
129
|
@router.get(
|
46
130
|
"",
|
47
|
-
response_model=Page[StackResponse],
|
48
131
|
responses={401: error_response, 404: error_response, 422: error_response},
|
49
132
|
)
|
133
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
134
|
+
# and can be removed after the migration
|
135
|
+
@workspace_router.get(
|
136
|
+
"/{workspace_name_or_id}" + STACKS,
|
137
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
138
|
+
deprecated=True,
|
139
|
+
tags=["stacks"],
|
140
|
+
)
|
50
141
|
@handle_exceptions
|
51
142
|
def list_stacks(
|
143
|
+
workspace_name_or_id: Optional[Union[str, UUID]] = None,
|
52
144
|
stack_filter_model: StackFilter = Depends(make_dependable(StackFilter)),
|
53
145
|
hydrate: bool = False,
|
54
146
|
_: AuthContext = Security(authorize),
|
55
147
|
) -> Page[StackResponse]:
|
56
|
-
"""Returns all stacks.
|
148
|
+
"""Returns all stacks, optionally filtered by workspace.
|
57
149
|
|
58
150
|
Args:
|
151
|
+
workspace_name_or_id: Optional name or ID of the workspace to filter by.
|
59
152
|
stack_filter_model: Filter model used for pagination, sorting,
|
60
153
|
filtering.
|
61
154
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
62
155
|
by including metadata fields in the response.
|
63
156
|
|
64
157
|
Returns:
|
65
|
-
All stacks.
|
158
|
+
All stacks matching the filter criteria.
|
66
159
|
"""
|
67
160
|
return verify_permissions_and_list_entities(
|
68
161
|
filter_model=stack_filter_model,
|
@@ -74,7 +167,6 @@ def list_stacks(
|
|
74
167
|
|
75
168
|
@router.get(
|
76
169
|
"/{stack_id}",
|
77
|
-
response_model=StackResponse,
|
78
170
|
responses={401: error_response, 404: error_response, 422: error_response},
|
79
171
|
)
|
80
172
|
@handle_exceptions
|
@@ -100,7 +192,6 @@ def get_stack(
|
|
100
192
|
|
101
193
|
@router.put(
|
102
194
|
"/{stack_id}",
|
103
|
-
response_model=StackResponse,
|
104
195
|
responses={401: error_response, 404: error_response, 422: error_response},
|
105
196
|
)
|
106
197
|
@handle_exceptions
|
@@ -37,6 +37,9 @@ from zenml.models import (
|
|
37
37
|
)
|
38
38
|
from zenml.zen_server.auth import AuthContext, authorize
|
39
39
|
from zenml.zen_server.exceptions import error_response
|
40
|
+
from zenml.zen_server.rbac.endpoint_utils import (
|
41
|
+
verify_permissions_and_create_entity,
|
42
|
+
)
|
40
43
|
from zenml.zen_server.rbac.models import Action, ResourceType
|
41
44
|
from zenml.zen_server.rbac.utils import (
|
42
45
|
dehydrate_page,
|
@@ -47,6 +50,7 @@ from zenml.zen_server.rbac.utils import (
|
|
47
50
|
from zenml.zen_server.utils import (
|
48
51
|
handle_exceptions,
|
49
52
|
make_dependable,
|
53
|
+
set_filter_workspace_scope,
|
50
54
|
zen_store,
|
51
55
|
)
|
52
56
|
|
@@ -59,7 +63,6 @@ router = APIRouter(
|
|
59
63
|
|
60
64
|
@router.get(
|
61
65
|
"",
|
62
|
-
response_model=Page[StepRunResponse],
|
63
66
|
responses={401: error_response, 404: error_response, 422: error_response},
|
64
67
|
)
|
65
68
|
@handle_exceptions
|
@@ -82,8 +85,14 @@ def list_run_steps(
|
|
82
85
|
Returns:
|
83
86
|
The run steps according to query filters.
|
84
87
|
"""
|
88
|
+
# A workspace scoped request must always be scoped to a specific
|
89
|
+
# workspace. This is required for the RBAC check to work.
|
90
|
+
set_filter_workspace_scope(step_run_filter_model)
|
91
|
+
assert isinstance(step_run_filter_model.workspace, UUID)
|
92
|
+
|
85
93
|
allowed_pipeline_run_ids = get_allowed_resource_ids(
|
86
|
-
resource_type=ResourceType.PIPELINE_RUN
|
94
|
+
resource_type=ResourceType.PIPELINE_RUN,
|
95
|
+
workspace_id=step_run_filter_model.workspace,
|
87
96
|
)
|
88
97
|
step_run_filter_model.configure_rbac(
|
89
98
|
authenticated_user_id=auth_context.user.id,
|
@@ -98,7 +107,6 @@ def list_run_steps(
|
|
98
107
|
|
99
108
|
@router.post(
|
100
109
|
"",
|
101
|
-
response_model=StepRunResponse,
|
102
110
|
responses={401: error_response, 409: error_response, 422: error_response},
|
103
111
|
)
|
104
112
|
@handle_exceptions
|
@@ -110,20 +118,22 @@ def create_run_step(
|
|
110
118
|
|
111
119
|
Args:
|
112
120
|
step: The run step to create.
|
121
|
+
_: Authentication context.
|
113
122
|
|
114
123
|
Returns:
|
115
124
|
The created run step.
|
116
125
|
"""
|
117
126
|
pipeline_run = zen_store().get_run(step.pipeline_run_id)
|
118
|
-
verify_permission_for_model(pipeline_run, action=Action.UPDATE)
|
119
127
|
|
120
|
-
|
121
|
-
|
128
|
+
return verify_permissions_and_create_entity(
|
129
|
+
request_model=step,
|
130
|
+
create_method=zen_store().create_run_step,
|
131
|
+
surrogate_models=[pipeline_run],
|
132
|
+
)
|
122
133
|
|
123
134
|
|
124
135
|
@router.get(
|
125
136
|
"/{step_id}",
|
126
|
-
response_model=StepRunResponse,
|
127
137
|
responses={401: error_response, 404: error_response, 422: error_response},
|
128
138
|
)
|
129
139
|
@handle_exceptions
|
@@ -157,7 +167,6 @@ def get_step(
|
|
157
167
|
|
158
168
|
@router.put(
|
159
169
|
"/{step_id}",
|
160
|
-
response_model=StepRunResponse,
|
161
170
|
responses={401: error_response, 404: error_response, 422: error_response},
|
162
171
|
)
|
163
172
|
@handle_exceptions
|
@@ -187,7 +196,6 @@ def update_step(
|
|
187
196
|
|
188
197
|
@router.get(
|
189
198
|
"/{step_id}" + STEP_CONFIGURATION,
|
190
|
-
response_model=Dict[str, Any],
|
191
199
|
responses={401: error_response, 404: error_response, 422: error_response},
|
192
200
|
)
|
193
201
|
@handle_exceptions
|
@@ -212,7 +220,6 @@ def get_step_configuration(
|
|
212
220
|
|
213
221
|
@router.get(
|
214
222
|
"/{step_id}" + STATUS,
|
215
|
-
response_model=ExecutionStatus,
|
216
223
|
responses={401: error_response, 404: error_response, 422: error_response},
|
217
224
|
)
|
218
225
|
@handle_exceptions
|
@@ -237,7 +244,6 @@ def get_step_status(
|
|
237
244
|
|
238
245
|
@router.get(
|
239
246
|
"/{step_id}" + LOGS,
|
240
|
-
response_model=str,
|
241
247
|
responses={401: error_response, 404: error_response, 422: error_response},
|
242
248
|
)
|
243
249
|
@handle_exceptions
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2023. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Endpoint definitions for the link between tags and resources."""
|
15
|
+
|
16
|
+
from typing import List
|
17
|
+
|
18
|
+
from fastapi import APIRouter, Security
|
19
|
+
|
20
|
+
from zenml.constants import (
|
21
|
+
API,
|
22
|
+
BATCH,
|
23
|
+
TAG_RESOURCES,
|
24
|
+
VERSION_1,
|
25
|
+
)
|
26
|
+
from zenml.models import TagResourceRequest, TagResourceResponse
|
27
|
+
from zenml.zen_server.auth import AuthContext, authorize
|
28
|
+
from zenml.zen_server.exceptions import error_response
|
29
|
+
from zenml.zen_server.utils import (
|
30
|
+
handle_exceptions,
|
31
|
+
zen_store,
|
32
|
+
)
|
33
|
+
|
34
|
+
router = APIRouter(
|
35
|
+
prefix=API + VERSION_1 + TAG_RESOURCES,
|
36
|
+
tags=["tag_resources"],
|
37
|
+
responses={401: error_response, 403: error_response},
|
38
|
+
)
|
39
|
+
|
40
|
+
|
41
|
+
@router.post(
|
42
|
+
"",
|
43
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
44
|
+
)
|
45
|
+
@handle_exceptions
|
46
|
+
def create_tag_resource(
|
47
|
+
tag_resource: TagResourceRequest,
|
48
|
+
_: AuthContext = Security(authorize),
|
49
|
+
) -> TagResourceResponse:
|
50
|
+
"""Attach different tags to different resources.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
tag_resource: A tag resource request.
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
A tag resource response.
|
57
|
+
"""
|
58
|
+
return zen_store().create_tag_resource(tag_resource=tag_resource)
|
59
|
+
|
60
|
+
|
61
|
+
@router.post(
|
62
|
+
BATCH,
|
63
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
64
|
+
)
|
65
|
+
@handle_exceptions
|
66
|
+
def batch_create_tag_resource(
|
67
|
+
tag_resources: List[TagResourceRequest],
|
68
|
+
_: AuthContext = Security(authorize),
|
69
|
+
) -> List[TagResourceResponse]:
|
70
|
+
"""Attach different tags to different resources.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
tag_resources: A list of tag resource requests.
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
A list of tag resource responses.
|
77
|
+
"""
|
78
|
+
return [
|
79
|
+
zen_store().create_tag_resource(tag_resource=tag_resource)
|
80
|
+
for tag_resource in tag_resources
|
81
|
+
]
|
82
|
+
|
83
|
+
|
84
|
+
@router.delete(
|
85
|
+
"",
|
86
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
87
|
+
)
|
88
|
+
@handle_exceptions
|
89
|
+
def delete_tag_resource(
|
90
|
+
tag_resource: TagResourceRequest,
|
91
|
+
_: AuthContext = Security(authorize),
|
92
|
+
) -> None:
|
93
|
+
"""Detach a tag from a resource.
|
94
|
+
|
95
|
+
Args:
|
96
|
+
tag_resource: The tag resource relationship to delete.
|
97
|
+
"""
|
98
|
+
zen_store().delete_tag_resource(tag_resource=tag_resource)
|
99
|
+
|
100
|
+
|
101
|
+
@router.delete(
|
102
|
+
BATCH,
|
103
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
104
|
+
)
|
105
|
+
@handle_exceptions
|
106
|
+
def batch_delete_tag_resource(
|
107
|
+
tag_resources: List[TagResourceRequest],
|
108
|
+
_: AuthContext = Security(authorize),
|
109
|
+
) -> None:
|
110
|
+
"""Detach different tags from different resources.
|
111
|
+
|
112
|
+
Args:
|
113
|
+
tag_resources: A list of tag resource requests.
|
114
|
+
"""
|
115
|
+
zen_store().batch_delete_tag_resource(tag_resources=tag_resources)
|
@@ -33,13 +33,10 @@ from zenml.models import (
|
|
33
33
|
from zenml.zen_server.auth import AuthContext, authorize
|
34
34
|
from zenml.zen_server.exceptions import error_response
|
35
35
|
from zenml.zen_server.rbac.endpoint_utils import (
|
36
|
-
verify_permissions_and_create_entity,
|
37
36
|
verify_permissions_and_delete_entity,
|
38
37
|
verify_permissions_and_get_entity,
|
39
|
-
verify_permissions_and_list_entities,
|
40
38
|
verify_permissions_and_update_entity,
|
41
39
|
)
|
42
|
-
from zenml.zen_server.rbac.models import ResourceType
|
43
40
|
from zenml.zen_server.utils import (
|
44
41
|
handle_exceptions,
|
45
42
|
make_dependable,
|
@@ -59,7 +56,6 @@ router = APIRouter(
|
|
59
56
|
|
60
57
|
@router.post(
|
61
58
|
"",
|
62
|
-
response_model=TagResponse,
|
63
59
|
responses={401: error_response, 409: error_response, 422: error_response},
|
64
60
|
)
|
65
61
|
@handle_exceptions
|
@@ -75,16 +71,11 @@ def create_tag(
|
|
75
71
|
Returns:
|
76
72
|
The created tag.
|
77
73
|
"""
|
78
|
-
return
|
79
|
-
request_model=tag,
|
80
|
-
resource_type=ResourceType.TAG,
|
81
|
-
create_method=zen_store().create_tag,
|
82
|
-
)
|
74
|
+
return zen_store().create_tag(tag=tag)
|
83
75
|
|
84
76
|
|
85
77
|
@router.get(
|
86
78
|
"",
|
87
|
-
response_model=Page[TagResponse],
|
88
79
|
responses={401: error_response, 404: error_response, 422: error_response},
|
89
80
|
)
|
90
81
|
@handle_exceptions
|
@@ -104,17 +95,14 @@ def list_tags(
|
|
104
95
|
Returns:
|
105
96
|
The tags according to query filters.
|
106
97
|
"""
|
107
|
-
return
|
108
|
-
|
109
|
-
resource_type=ResourceType.TAG,
|
110
|
-
list_method=zen_store().list_tags,
|
98
|
+
return zen_store().list_tags(
|
99
|
+
tag_filter_model=tag_filter_model,
|
111
100
|
hydrate=hydrate,
|
112
101
|
)
|
113
102
|
|
114
103
|
|
115
104
|
@router.get(
|
116
105
|
"/{tag_name_or_id}",
|
117
|
-
response_model=TagResponse,
|
118
106
|
responses={401: error_response, 404: error_response, 422: error_response},
|
119
107
|
)
|
120
108
|
@handle_exceptions
|
@@ -134,13 +122,14 @@ def get_tag(
|
|
134
122
|
The tag with the given name or ID.
|
135
123
|
"""
|
136
124
|
return verify_permissions_and_get_entity(
|
137
|
-
id=tag_name_or_id,
|
125
|
+
id=tag_name_or_id,
|
126
|
+
get_method=zen_store().get_tag,
|
127
|
+
hydrate=hydrate,
|
138
128
|
)
|
139
129
|
|
140
130
|
|
141
131
|
@router.put(
|
142
132
|
"/{tag_id}",
|
143
|
-
response_model=TagResponse,
|
144
133
|
responses={401: error_response, 404: error_response, 422: error_response},
|
145
134
|
)
|
146
135
|
@handle_exceptions
|
@@ -58,7 +58,6 @@ router = APIRouter(
|
|
58
58
|
|
59
59
|
@router.get(
|
60
60
|
"",
|
61
|
-
response_model=Page[TriggerResponse],
|
62
61
|
responses={401: error_response, 404: error_response, 422: error_response},
|
63
62
|
)
|
64
63
|
@handle_exceptions
|
@@ -90,7 +89,6 @@ def list_triggers(
|
|
90
89
|
|
91
90
|
@router.get(
|
92
91
|
"/{trigger_id}",
|
93
|
-
response_model=TriggerResponse,
|
94
92
|
responses={401: error_response, 404: error_response, 422: error_response},
|
95
93
|
)
|
96
94
|
@handle_exceptions
|
@@ -116,7 +114,6 @@ def get_trigger(
|
|
116
114
|
|
117
115
|
@router.post(
|
118
116
|
"",
|
119
|
-
response_model=TriggerResponse,
|
120
117
|
responses={401: error_response, 409: error_response, 422: error_response},
|
121
118
|
)
|
122
119
|
@handle_exceptions
|
@@ -162,14 +159,12 @@ def create_trigger(
|
|
162
159
|
|
163
160
|
return verify_permissions_and_create_entity(
|
164
161
|
request_model=trigger,
|
165
|
-
resource_type=ResourceType.TRIGGER,
|
166
162
|
create_method=zen_store().create_trigger,
|
167
163
|
)
|
168
164
|
|
169
165
|
|
170
166
|
@router.put(
|
171
167
|
"/{trigger_id}",
|
172
|
-
response_model=TriggerResponse,
|
173
168
|
responses={401: error_response, 404: error_response, 422: error_response},
|
174
169
|
)
|
175
170
|
@handle_exceptions
|
@@ -245,9 +240,11 @@ def delete_trigger(
|
|
245
240
|
Args:
|
246
241
|
trigger_id: Name of the trigger.
|
247
242
|
"""
|
248
|
-
|
249
|
-
|
250
|
-
|
243
|
+
verify_permissions_and_delete_entity(
|
244
|
+
id=trigger_id,
|
245
|
+
get_method=zen_store().get_trigger,
|
246
|
+
delete_method=zen_store().delete_trigger,
|
247
|
+
)
|
251
248
|
|
252
249
|
|
253
250
|
executions_router = APIRouter(
|
@@ -38,6 +38,7 @@ from zenml.models import (
|
|
38
38
|
UserRequest,
|
39
39
|
UserResponse,
|
40
40
|
UserUpdate,
|
41
|
+
WorkspaceScopedResponse,
|
41
42
|
)
|
42
43
|
from zenml.zen_server.auth import (
|
43
44
|
AuthContext,
|
@@ -46,6 +47,9 @@ from zenml.zen_server.auth import (
|
|
46
47
|
)
|
47
48
|
from zenml.zen_server.exceptions import error_response
|
48
49
|
from zenml.zen_server.rate_limit import RequestLimiter
|
50
|
+
from zenml.zen_server.rbac.endpoint_utils import (
|
51
|
+
verify_permissions_and_get_entity,
|
52
|
+
)
|
49
53
|
from zenml.zen_server.rbac.models import Action, Resource, ResourceType
|
50
54
|
from zenml.zen_server.rbac.utils import (
|
51
55
|
dehydrate_page,
|
@@ -87,7 +91,6 @@ current_user_router = APIRouter(
|
|
87
91
|
|
88
92
|
@router.get(
|
89
93
|
"",
|
90
|
-
response_model=Page[UserResponse],
|
91
94
|
responses={401: error_response, 404: error_response, 422: error_response},
|
92
95
|
)
|
93
96
|
@handle_exceptions
|
@@ -133,7 +136,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
133
136
|
|
134
137
|
@router.post(
|
135
138
|
"",
|
136
|
-
response_model=UserResponse,
|
137
139
|
responses={
|
138
140
|
401: error_response,
|
139
141
|
409: error_response,
|
@@ -174,7 +176,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
174
176
|
|
175
177
|
# new_user = verify_permissions_and_create_entity(
|
176
178
|
# request_model=user,
|
177
|
-
# resource_type=ResourceType.USER,
|
178
179
|
# create_method=zen_store().create_user,
|
179
180
|
# )
|
180
181
|
new_user = zen_store().create_user(user)
|
@@ -188,7 +189,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
188
189
|
|
189
190
|
@router.get(
|
190
191
|
"/{user_name_or_id}",
|
191
|
-
response_model=UserResponse,
|
192
192
|
responses={401: error_response, 404: error_response, 422: error_response},
|
193
193
|
)
|
194
194
|
@handle_exceptions
|
@@ -233,7 +233,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
233
233
|
|
234
234
|
@router.put(
|
235
235
|
"/{user_name_or_id}",
|
236
|
-
response_model=UserResponse,
|
237
236
|
responses={
|
238
237
|
401: error_response,
|
239
238
|
404: error_response,
|
@@ -403,7 +402,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
403
402
|
|
404
403
|
@activation_router.put(
|
405
404
|
"/{user_name_or_id}" + ACTIVATE,
|
406
|
-
response_model=UserResponse,
|
407
405
|
responses={
|
408
406
|
401: error_response,
|
409
407
|
404: error_response,
|
@@ -464,7 +462,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
464
462
|
|
465
463
|
@router.put(
|
466
464
|
"/{user_name_or_id}" + DEACTIVATE,
|
467
|
-
response_model=UserResponse,
|
468
465
|
responses={
|
469
466
|
401: error_response,
|
470
467
|
404: error_response,
|
@@ -555,7 +552,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
555
552
|
|
556
553
|
@router.put(
|
557
554
|
"/{user_name_or_id}" + EMAIL_ANALYTICS,
|
558
|
-
response_model=UserResponse,
|
559
555
|
responses={
|
560
556
|
401: error_response,
|
561
557
|
404: error_response,
|
@@ -608,7 +604,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
608
604
|
|
609
605
|
@current_user_router.get(
|
610
606
|
"/current-user",
|
611
|
-
response_model=UserResponse,
|
612
607
|
responses={401: error_response, 404: error_response, 422: error_response},
|
613
608
|
)
|
614
609
|
@handle_exceptions
|
@@ -632,7 +627,6 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
632
627
|
|
633
628
|
@current_user_router.put(
|
634
629
|
"/current-user",
|
635
|
-
response_model=UserResponse,
|
636
630
|
responses={
|
637
631
|
401: error_response,
|
638
632
|
404: error_response,
|
@@ -752,8 +746,6 @@ if server_config().rbac_enabled:
|
|
752
746
|
)
|
753
747
|
|
754
748
|
resource_type = ResourceType(resource_type)
|
755
|
-
resource = Resource(type=resource_type, id=resource_id)
|
756
|
-
|
757
749
|
schema_class = get_schema_for_resource_type(resource_type)
|
758
750
|
model = zen_store().get_entity_by_id(
|
759
751
|
entity_id=resource_id, schema_class=schema_class
|
@@ -765,6 +757,14 @@ if server_config().rbac_enabled:
|
|
765
757
|
"not exist."
|
766
758
|
)
|
767
759
|
|
760
|
+
workspace_id = None
|
761
|
+
if isinstance(model, WorkspaceScopedResponse):
|
762
|
+
workspace_id = model.workspace.id
|
763
|
+
|
764
|
+
resource = Resource(
|
765
|
+
type=resource_type, id=resource_id, workspace_id=workspace_id
|
766
|
+
)
|
767
|
+
|
768
768
|
verify_permission_for_model(model=model, action=Action.SHARE)
|
769
769
|
for action in actions:
|
770
770
|
# Make sure users aren't able to share permissions they don't have
|
@@ -776,3 +776,38 @@ if server_config().rbac_enabled:
|
|
776
776
|
resource=resource,
|
777
777
|
actions=[Action(action) for action in actions],
|
778
778
|
)
|
779
|
+
|
780
|
+
|
781
|
+
@current_user_router.put(
|
782
|
+
"/default-workspace",
|
783
|
+
responses={
|
784
|
+
401: error_response,
|
785
|
+
404: error_response,
|
786
|
+
422: error_response,
|
787
|
+
},
|
788
|
+
)
|
789
|
+
@handle_exceptions
|
790
|
+
def update_user_default_workspace(
|
791
|
+
workspace_name_or_id: Union[str, UUID],
|
792
|
+
auth_context: AuthContext = Security(authorize),
|
793
|
+
) -> UserResponse:
|
794
|
+
"""Updates the default workspace of the current user.
|
795
|
+
|
796
|
+
Args:
|
797
|
+
workspace_name_or_id: Name or ID of the workspace.
|
798
|
+
auth_context: Authentication context.
|
799
|
+
|
800
|
+
Returns:
|
801
|
+
The updated user.
|
802
|
+
"""
|
803
|
+
workspace = verify_permissions_and_get_entity(
|
804
|
+
id=workspace_name_or_id,
|
805
|
+
get_method=zen_store().get_workspace,
|
806
|
+
)
|
807
|
+
|
808
|
+
user = zen_store().update_user(
|
809
|
+
user_id=auth_context.user.id,
|
810
|
+
user_update=UserUpdate(default_workspace_id=workspace.id),
|
811
|
+
)
|
812
|
+
|
813
|
+
return dehydrate_response_model(user)
|