zenml-nightly 0.75.0.dev20250312__py3-none-any.whl → 0.75.0.dev20250314__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zenml/VERSION +1 -1
- zenml/__init__.py +2 -0
- zenml/analytics/context.py +7 -0
- zenml/analytics/enums.py +2 -2
- zenml/artifacts/utils.py +2 -4
- zenml/cli/__init__.py +8 -9
- zenml/cli/base.py +2 -2
- zenml/cli/code_repository.py +1 -1
- zenml/cli/login.py +6 -0
- zenml/cli/model.py +7 -15
- zenml/cli/pipeline.py +3 -3
- zenml/cli/project.py +172 -0
- zenml/cli/secret.py +47 -44
- zenml/cli/service_accounts.py +0 -1
- zenml/cli/service_connectors.py +15 -17
- zenml/cli/stack.py +0 -3
- zenml/cli/stack_components.py +2 -2
- zenml/cli/tag.py +3 -5
- zenml/cli/utils.py +25 -23
- zenml/client.py +749 -475
- zenml/config/global_config.py +48 -37
- 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 +6 -6
- 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/gcp/service_connectors/gcp_service_connector.py +7 -6
- zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +1 -4
- zenml/integrations/mlflow/steps/mlflow_registry.py +3 -3
- zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -1
- zenml/integrations/wandb/__init__.py +1 -1
- zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py +29 -9
- zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +5 -3
- zenml/model/model.py +10 -10
- zenml/model_registries/base_model_registry.py +1 -1
- zenml/models/__init__.py +45 -28
- zenml/models/v2/base/base.py +0 -5
- zenml/models/v2/base/filter.py +2 -2
- zenml/models/v2/base/scoped.py +135 -156
- zenml/models/v2/core/action.py +12 -12
- zenml/models/v2/core/api_key.py +1 -1
- zenml/models/v2/core/artifact.py +31 -18
- zenml/models/v2/core/artifact_version.py +57 -40
- zenml/models/v2/core/code_repository.py +12 -12
- zenml/models/v2/core/component.py +22 -33
- zenml/models/v2/core/device.py +3 -2
- zenml/models/v2/core/event_source.py +14 -14
- zenml/models/v2/core/flavor.py +19 -47
- zenml/models/v2/core/logs.py +1 -2
- zenml/models/v2/core/model.py +23 -20
- zenml/models/v2/core/model_version.py +51 -42
- zenml/models/v2/core/pipeline.py +16 -16
- zenml/models/v2/core/pipeline_build.py +14 -14
- zenml/models/v2/core/pipeline_deployment.py +12 -14
- zenml/models/v2/core/pipeline_run.py +21 -29
- zenml/models/v2/core/project.py +203 -0
- zenml/models/v2/core/run_metadata.py +2 -2
- zenml/models/v2/core/run_template.py +16 -17
- zenml/models/v2/core/schedule.py +12 -21
- zenml/models/v2/core/secret.py +94 -128
- zenml/models/v2/core/server_settings.py +2 -2
- zenml/models/v2/core/service.py +57 -26
- zenml/models/v2/core/service_connector.py +14 -16
- zenml/models/v2/core/stack.py +24 -26
- zenml/models/v2/core/step_run.py +16 -28
- zenml/models/v2/core/tag.py +41 -15
- zenml/models/v2/core/trigger.py +13 -13
- zenml/models/v2/core/trigger_execution.py +2 -2
- zenml/models/v2/core/user.py +2 -2
- zenml/models/v2/misc/statistics.py +45 -0
- zenml/models/v2/misc/tag.py +27 -0
- zenml/orchestrators/cache_utils.py +7 -7
- zenml/orchestrators/input_utils.py +1 -0
- zenml/orchestrators/step_launcher.py +1 -2
- zenml/orchestrators/step_run_utils.py +2 -4
- zenml/orchestrators/step_runner.py +10 -1
- zenml/orchestrators/utils.py +4 -4
- zenml/pipelines/build_utils.py +2 -4
- zenml/pipelines/pipeline_decorator.py +3 -2
- zenml/pipelines/pipeline_definition.py +8 -9
- zenml/pipelines/run_utils.py +4 -4
- zenml/service_connectors/service_connector.py +0 -10
- zenml/service_connectors/service_connector_utils.py +0 -2
- zenml/stack/authentication_mixin.py +1 -1
- zenml/stack/flavor.py +3 -14
- zenml/stack/stack.py +0 -1
- zenml/stack/stack_component.py +1 -5
- zenml/steps/base_step.py +10 -2
- 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 +155 -30
- zenml/zen_server/rbac/zenml_cloud_rbac.py +39 -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 +54 -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 +100 -23
- zenml/zen_server/routers/models_endpoints.py +50 -69
- zenml/zen_server/routers/pipeline_builds_endpoints.py +55 -3
- zenml/zen_server/routers/pipeline_deployments_endpoints.py +56 -4
- zenml/zen_server/routers/pipelines_endpoints.py +70 -3
- zenml/zen_server/routers/plugin_endpoints.py +0 -1
- zenml/zen_server/routers/projects_endpoints.py +283 -0
- zenml/zen_server/routers/run_metadata_endpoints.py +97 -0
- zenml/zen_server/routers/run_templates_endpoints.py +64 -3
- zenml/zen_server/routers/runs_endpoints.py +58 -8
- zenml/zen_server/routers/schedule_endpoints.py +67 -6
- zenml/zen_server/routers/secrets_endpoints.py +38 -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 +94 -14
- zenml/zen_server/routers/service_endpoints.py +18 -7
- zenml/zen_server/routers/stack_components_endpoints.py +66 -7
- zenml/zen_server/routers/stacks_endpoints.py +95 -6
- 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 +9 -12
- zenml/zen_server/template_execution/utils.py +8 -7
- zenml/zen_server/utils.py +21 -0
- zenml/zen_server/zen_server_api.py +7 -2
- zenml/zen_stores/base_zen_store.py +50 -69
- zenml/zen_stores/migrations/versions/12eff0206201_rename_workspace_to_project.py +768 -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/cbc6acd71f92_add_workspace_display_name.py +58 -0
- 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 +223 -230
- zenml/zen_stores/schemas/__init__.py +2 -2
- zenml/zen_stores/schemas/action_schemas.py +15 -8
- zenml/zen_stores/schemas/api_key_schemas.py +8 -1
- zenml/zen_stores/schemas/artifact_schemas.py +35 -10
- zenml/zen_stores/schemas/code_repository_schemas.py +22 -17
- zenml/zen_stores/schemas/component_schemas.py +9 -14
- zenml/zen_stores/schemas/event_source_schemas.py +15 -8
- zenml/zen_stores/schemas/flavor_schemas.py +14 -20
- zenml/zen_stores/schemas/model_schemas.py +18 -17
- zenml/zen_stores/schemas/pipeline_build_schemas.py +7 -7
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +10 -8
- zenml/zen_stores/schemas/pipeline_run_schemas.py +9 -12
- zenml/zen_stores/schemas/pipeline_schemas.py +9 -9
- zenml/zen_stores/schemas/{workspace_schemas.py → project_schemas.py} +53 -65
- zenml/zen_stores/schemas/run_metadata_schemas.py +5 -5
- zenml/zen_stores/schemas/run_template_schemas.py +17 -13
- zenml/zen_stores/schemas/schedule_schema.py +16 -21
- 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 +7 -8
- zenml/zen_stores/schemas/stack_schemas.py +12 -15
- zenml/zen_stores/schemas/step_run_schemas.py +14 -15
- zenml/zen_stores/schemas/tag_schemas.py +30 -2
- zenml/zen_stores/schemas/trigger_schemas.py +15 -8
- zenml/zen_stores/schemas/user_schemas.py +12 -2
- zenml/zen_stores/schemas/utils.py +16 -0
- zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +0 -3
- zenml/zen_stores/sql_zen_store.py +2984 -2369
- zenml/zen_stores/template_utils.py +1 -1
- zenml/zen_stores/zen_store_interface.py +136 -126
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/METADATA +1 -1
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/RECORD +188 -173
- zenml/cli/workspace.py +0 -86
- zenml/models/v2/core/workspace.py +0 -131
- zenml/zen_server/routers/workspaces_endpoints.py +0 -1469
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/entry_points.txt +0 -0
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for services."""
|
15
15
|
|
16
|
+
from typing import Optional, Union
|
16
17
|
from uuid import UUID
|
17
18
|
|
18
19
|
from fastapi import APIRouter, Depends, Security
|
@@ -35,6 +36,7 @@ from zenml.zen_server.rbac.endpoint_utils import (
|
|
35
36
|
verify_permissions_and_update_entity,
|
36
37
|
)
|
37
38
|
from zenml.zen_server.rbac.models import ResourceType
|
39
|
+
from zenml.zen_server.routers.projects_endpoints import workspace_router
|
38
40
|
from zenml.zen_server.utils import (
|
39
41
|
handle_exceptions,
|
40
42
|
make_dependable,
|
@@ -50,32 +52,43 @@ router = APIRouter(
|
|
50
52
|
|
51
53
|
@router.post(
|
52
54
|
"",
|
53
|
-
response_model=ServiceResponse,
|
54
55
|
responses={401: error_response, 422: error_response},
|
55
56
|
)
|
57
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
58
|
+
# and can be removed after the migration
|
59
|
+
@workspace_router.post(
|
60
|
+
"/{project_name_or_id}" + SERVICES,
|
61
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
62
|
+
deprecated=True,
|
63
|
+
tags=["services"],
|
64
|
+
)
|
56
65
|
@handle_exceptions
|
57
66
|
def create_service(
|
58
67
|
service: ServiceRequest,
|
68
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
59
69
|
_: AuthContext = Security(authorize),
|
60
70
|
) -> ServiceResponse:
|
61
71
|
"""Creates a new service.
|
62
72
|
|
63
73
|
Args:
|
64
|
-
service: The
|
74
|
+
service: The service to create.
|
75
|
+
project_name_or_id: Optional name or ID of the project.
|
65
76
|
|
66
77
|
Returns:
|
67
|
-
The created service
|
78
|
+
The created service.
|
68
79
|
"""
|
80
|
+
if project_name_or_id:
|
81
|
+
project = zen_store().get_project(project_name_or_id)
|
82
|
+
service.project = project.id
|
83
|
+
|
69
84
|
return verify_permissions_and_create_entity(
|
70
85
|
request_model=service,
|
71
86
|
create_method=zen_store().create_service,
|
72
|
-
resource_type=ResourceType.SERVICE,
|
73
87
|
)
|
74
88
|
|
75
89
|
|
76
90
|
@router.get(
|
77
91
|
"",
|
78
|
-
response_model=Page[ServiceResponse],
|
79
92
|
responses={401: error_response, 404: error_response, 422: error_response},
|
80
93
|
)
|
81
94
|
@handle_exceptions
|
@@ -105,7 +118,6 @@ def list_services(
|
|
105
118
|
|
106
119
|
@router.get(
|
107
120
|
"/{service_id}",
|
108
|
-
response_model=ServiceResponse,
|
109
121
|
responses={401: error_response, 404: error_response, 422: error_response},
|
110
122
|
)
|
111
123
|
@handle_exceptions
|
@@ -133,7 +145,6 @@ def get_service(
|
|
133
145
|
|
134
146
|
@router.put(
|
135
147
|
"/{service_id}",
|
136
|
-
response_model=ServiceResponse,
|
137
148
|
responses={401: error_response, 404: error_response, 422: error_response},
|
138
149
|
)
|
139
150
|
@handle_exceptions
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for stack components."""
|
15
15
|
|
16
|
-
from typing import List
|
16
|
+
from typing import List, Optional, Union
|
17
17
|
from uuid import UUID
|
18
18
|
|
19
19
|
from fastapi import APIRouter, Depends, Security
|
@@ -22,6 +22,7 @@ from zenml.constants import API, COMPONENT_TYPES, STACK_COMPONENTS, VERSION_1
|
|
22
22
|
from zenml.enums import StackComponentType
|
23
23
|
from zenml.models import (
|
24
24
|
ComponentFilter,
|
25
|
+
ComponentRequest,
|
25
26
|
ComponentResponse,
|
26
27
|
ComponentUpdate,
|
27
28
|
Page,
|
@@ -29,6 +30,7 @@ from zenml.models import (
|
|
29
30
|
from zenml.zen_server.auth import AuthContext, authorize
|
30
31
|
from zenml.zen_server.exceptions import error_response
|
31
32
|
from zenml.zen_server.rbac.endpoint_utils import (
|
33
|
+
verify_permissions_and_create_entity,
|
32
34
|
verify_permissions_and_delete_entity,
|
33
35
|
verify_permissions_and_get_entity,
|
34
36
|
verify_permissions_and_list_entities,
|
@@ -36,6 +38,7 @@ from zenml.zen_server.rbac.endpoint_utils import (
|
|
36
38
|
)
|
37
39
|
from zenml.zen_server.rbac.models import Action, ResourceType
|
38
40
|
from zenml.zen_server.rbac.utils import verify_permission_for_model
|
41
|
+
from zenml.zen_server.routers.projects_endpoints import workspace_router
|
39
42
|
from zenml.zen_server.utils import (
|
40
43
|
handle_exceptions,
|
41
44
|
make_dependable,
|
@@ -55,29 +58,88 @@ types_router = APIRouter(
|
|
55
58
|
)
|
56
59
|
|
57
60
|
|
61
|
+
@router.post(
|
62
|
+
"",
|
63
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
64
|
+
)
|
65
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
66
|
+
# and can be removed after the migration
|
67
|
+
@workspace_router.post(
|
68
|
+
"/{project_name_or_id}" + STACK_COMPONENTS,
|
69
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
70
|
+
deprecated=True,
|
71
|
+
tags=["stack_components"],
|
72
|
+
)
|
73
|
+
@handle_exceptions
|
74
|
+
def create_stack_component(
|
75
|
+
component: ComponentRequest,
|
76
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
77
|
+
_: AuthContext = Security(authorize),
|
78
|
+
) -> ComponentResponse:
|
79
|
+
"""Creates a stack component.
|
80
|
+
|
81
|
+
Args:
|
82
|
+
component: Stack component to register.
|
83
|
+
project_name_or_id: Optional name or ID of the project.
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
The created stack component.
|
87
|
+
"""
|
88
|
+
if component.connector:
|
89
|
+
service_connector = zen_store().get_service_connector(
|
90
|
+
component.connector
|
91
|
+
)
|
92
|
+
verify_permission_for_model(service_connector, action=Action.READ)
|
93
|
+
|
94
|
+
from zenml.stack.utils import validate_stack_component_config
|
95
|
+
|
96
|
+
validate_stack_component_config(
|
97
|
+
configuration_dict=component.configuration,
|
98
|
+
flavor=component.flavor,
|
99
|
+
component_type=component.type,
|
100
|
+
zen_store=zen_store(),
|
101
|
+
# We allow custom flavors to fail import on the server side.
|
102
|
+
validate_custom_flavors=False,
|
103
|
+
)
|
104
|
+
|
105
|
+
return verify_permissions_and_create_entity(
|
106
|
+
request_model=component,
|
107
|
+
create_method=zen_store().create_stack_component,
|
108
|
+
)
|
109
|
+
|
110
|
+
|
58
111
|
@router.get(
|
59
112
|
"",
|
60
|
-
response_model=Page[ComponentResponse],
|
61
113
|
responses={401: error_response, 404: error_response, 422: error_response},
|
62
114
|
)
|
115
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
116
|
+
# and can be removed after the migration
|
117
|
+
@workspace_router.get(
|
118
|
+
"/{project_name_or_id}" + STACK_COMPONENTS,
|
119
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
120
|
+
deprecated=True,
|
121
|
+
tags=["stack_components"],
|
122
|
+
)
|
63
123
|
@handle_exceptions
|
64
124
|
def list_stack_components(
|
65
125
|
component_filter_model: ComponentFilter = Depends(
|
66
126
|
make_dependable(ComponentFilter)
|
67
127
|
),
|
128
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
68
129
|
hydrate: bool = False,
|
69
130
|
_: AuthContext = Security(authorize),
|
70
131
|
) -> Page[ComponentResponse]:
|
71
|
-
"""Get a list of all stack components
|
132
|
+
"""Get a list of all stack components.
|
72
133
|
|
73
134
|
Args:
|
74
135
|
component_filter_model: Filter model used for pagination, sorting,
|
75
136
|
filtering.
|
137
|
+
project_name_or_id: Optional name or ID of the project to filter by.
|
76
138
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
77
139
|
by including metadata fields in the response.
|
78
140
|
|
79
141
|
Returns:
|
80
|
-
List of stack components
|
142
|
+
List of stack components matching the filter criteria.
|
81
143
|
"""
|
82
144
|
return verify_permissions_and_list_entities(
|
83
145
|
filter_model=component_filter_model,
|
@@ -89,7 +151,6 @@ def list_stack_components(
|
|
89
151
|
|
90
152
|
@router.get(
|
91
153
|
"/{component_id}",
|
92
|
-
response_model=ComponentResponse,
|
93
154
|
responses={401: error_response, 404: error_response, 422: error_response},
|
94
155
|
)
|
95
156
|
@handle_exceptions
|
@@ -117,7 +178,6 @@ def get_stack_component(
|
|
117
178
|
|
118
179
|
@router.put(
|
119
180
|
"/{component_id}",
|
120
|
-
response_model=ComponentResponse,
|
121
181
|
responses={401: error_response, 404: error_response, 422: error_response},
|
122
182
|
)
|
123
183
|
@handle_exceptions
|
@@ -185,7 +245,6 @@ def deregister_stack_component(
|
|
185
245
|
|
186
246
|
@types_router.get(
|
187
247
|
"",
|
188
|
-
response_model=List[str],
|
189
248
|
responses={401: error_response, 404: error_response, 422: error_response},
|
190
249
|
)
|
191
250
|
@handle_exceptions
|
@@ -13,12 +13,19 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for stacks."""
|
15
15
|
|
16
|
+
from typing import Optional, Union
|
16
17
|
from uuid import UUID
|
17
18
|
|
18
19
|
from fastapi import APIRouter, Depends, Security
|
19
20
|
|
20
21
|
from zenml.constants import API, STACKS, VERSION_1
|
21
|
-
from zenml.models import
|
22
|
+
from zenml.models import (
|
23
|
+
Page,
|
24
|
+
StackFilter,
|
25
|
+
StackRequest,
|
26
|
+
StackResponse,
|
27
|
+
StackUpdate,
|
28
|
+
)
|
22
29
|
from zenml.zen_server.auth import AuthContext, authorize
|
23
30
|
from zenml.zen_server.exceptions import error_response
|
24
31
|
from zenml.zen_server.rbac.endpoint_utils import (
|
@@ -28,7 +35,12 @@ from zenml.zen_server.rbac.endpoint_utils import (
|
|
28
35
|
verify_permissions_and_update_entity,
|
29
36
|
)
|
30
37
|
from zenml.zen_server.rbac.models import Action, ResourceType
|
31
|
-
from zenml.zen_server.rbac.utils import
|
38
|
+
from zenml.zen_server.rbac.utils import (
|
39
|
+
batch_verify_permissions_for_models,
|
40
|
+
verify_permission,
|
41
|
+
verify_permission_for_model,
|
42
|
+
)
|
43
|
+
from zenml.zen_server.routers.projects_endpoints import workspace_router
|
32
44
|
from zenml.zen_server.utils import (
|
33
45
|
handle_exceptions,
|
34
46
|
make_dependable,
|
@@ -42,13 +54,91 @@ router = APIRouter(
|
|
42
54
|
)
|
43
55
|
|
44
56
|
|
57
|
+
@router.post(
|
58
|
+
"",
|
59
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
60
|
+
)
|
61
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
62
|
+
# and can be removed after the migration
|
63
|
+
@workspace_router.post(
|
64
|
+
"/{project_name_or_id}" + STACKS,
|
65
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
66
|
+
deprecated=True,
|
67
|
+
tags=["stacks"],
|
68
|
+
)
|
69
|
+
@handle_exceptions
|
70
|
+
def create_stack(
|
71
|
+
stack: StackRequest,
|
72
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
73
|
+
auth_context: AuthContext = Security(authorize),
|
74
|
+
) -> StackResponse:
|
75
|
+
"""Creates a stack.
|
76
|
+
|
77
|
+
Args:
|
78
|
+
stack: Stack to register.
|
79
|
+
project_name_or_id: Optional name or ID of the project.
|
80
|
+
auth_context: Authentication context.
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
The created stack.
|
84
|
+
"""
|
85
|
+
# Check the service connector creation
|
86
|
+
is_connector_create_needed = False
|
87
|
+
for connector_id_or_info in stack.service_connectors:
|
88
|
+
if isinstance(connector_id_or_info, UUID):
|
89
|
+
service_connector = zen_store().get_service_connector(
|
90
|
+
connector_id_or_info, hydrate=False
|
91
|
+
)
|
92
|
+
verify_permission_for_model(
|
93
|
+
model=service_connector, action=Action.READ
|
94
|
+
)
|
95
|
+
else:
|
96
|
+
is_connector_create_needed = True
|
97
|
+
|
98
|
+
# Check the component creation
|
99
|
+
if is_connector_create_needed:
|
100
|
+
verify_permission(
|
101
|
+
resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
|
102
|
+
)
|
103
|
+
is_component_create_needed = False
|
104
|
+
for components in stack.components.values():
|
105
|
+
for component_id_or_info in components:
|
106
|
+
if isinstance(component_id_or_info, UUID):
|
107
|
+
component = zen_store().get_stack_component(
|
108
|
+
component_id_or_info, hydrate=False
|
109
|
+
)
|
110
|
+
verify_permission_for_model(
|
111
|
+
model=component, action=Action.READ
|
112
|
+
)
|
113
|
+
else:
|
114
|
+
is_component_create_needed = True
|
115
|
+
if is_component_create_needed:
|
116
|
+
verify_permission(
|
117
|
+
resource_type=ResourceType.STACK_COMPONENT,
|
118
|
+
action=Action.CREATE,
|
119
|
+
)
|
120
|
+
|
121
|
+
# Check the stack creation
|
122
|
+
verify_permission_for_model(model=stack, action=Action.CREATE)
|
123
|
+
|
124
|
+
return zen_store().create_stack(stack)
|
125
|
+
|
126
|
+
|
45
127
|
@router.get(
|
46
128
|
"",
|
47
|
-
response_model=Page[StackResponse],
|
48
129
|
responses={401: error_response, 404: error_response, 422: error_response},
|
49
130
|
)
|
131
|
+
# TODO: the workspace scoped endpoint is only kept for dashboard compatibility
|
132
|
+
# and can be removed after the migration
|
133
|
+
@workspace_router.get(
|
134
|
+
"/{project_name_or_id}" + STACKS,
|
135
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
136
|
+
deprecated=True,
|
137
|
+
tags=["stacks"],
|
138
|
+
)
|
50
139
|
@handle_exceptions
|
51
140
|
def list_stacks(
|
141
|
+
project_name_or_id: Optional[Union[str, UUID]] = None,
|
52
142
|
stack_filter_model: StackFilter = Depends(make_dependable(StackFilter)),
|
53
143
|
hydrate: bool = False,
|
54
144
|
_: AuthContext = Security(authorize),
|
@@ -56,13 +146,14 @@ def list_stacks(
|
|
56
146
|
"""Returns all stacks.
|
57
147
|
|
58
148
|
Args:
|
149
|
+
project_name_or_id: Optional name or ID of the project to filter by.
|
59
150
|
stack_filter_model: Filter model used for pagination, sorting,
|
60
151
|
filtering.
|
61
152
|
hydrate: Flag deciding whether to hydrate the output model(s)
|
62
153
|
by including metadata fields in the response.
|
63
154
|
|
64
155
|
Returns:
|
65
|
-
All stacks.
|
156
|
+
All stacks matching the filter criteria.
|
66
157
|
"""
|
67
158
|
return verify_permissions_and_list_entities(
|
68
159
|
filter_model=stack_filter_model,
|
@@ -74,7 +165,6 @@ def list_stacks(
|
|
74
165
|
|
75
166
|
@router.get(
|
76
167
|
"/{stack_id}",
|
77
|
-
response_model=StackResponse,
|
78
168
|
responses={401: error_response, 404: error_response, 422: error_response},
|
79
169
|
)
|
80
170
|
@handle_exceptions
|
@@ -100,7 +190,6 @@ def get_stack(
|
|
100
190
|
|
101
191
|
@router.put(
|
102
192
|
"/{stack_id}",
|
103
|
-
response_model=StackResponse,
|
104
193
|
responses={401: error_response, 404: error_response, 422: error_response},
|
105
194
|
)
|
106
195
|
@handle_exceptions
|
@@ -37,6 +37,9 @@ from zenml.models import (
|
|
37
37
|
)
|
38
38
|
from zenml.zen_server.auth import AuthContext, authorize
|
39
39
|
from zenml.zen_server.exceptions import error_response
|
40
|
+
from zenml.zen_server.rbac.endpoint_utils import (
|
41
|
+
verify_permissions_and_create_entity,
|
42
|
+
)
|
40
43
|
from zenml.zen_server.rbac.models import Action, ResourceType
|
41
44
|
from zenml.zen_server.rbac.utils import (
|
42
45
|
dehydrate_page,
|
@@ -47,6 +50,7 @@ from zenml.zen_server.rbac.utils import (
|
|
47
50
|
from zenml.zen_server.utils import (
|
48
51
|
handle_exceptions,
|
49
52
|
make_dependable,
|
53
|
+
set_filter_project_scope,
|
50
54
|
zen_store,
|
51
55
|
)
|
52
56
|
|
@@ -59,7 +63,6 @@ router = APIRouter(
|
|
59
63
|
|
60
64
|
@router.get(
|
61
65
|
"",
|
62
|
-
response_model=Page[StepRunResponse],
|
63
66
|
responses={401: error_response, 404: error_response, 422: error_response},
|
64
67
|
)
|
65
68
|
@handle_exceptions
|
@@ -82,8 +85,14 @@ def list_run_steps(
|
|
82
85
|
Returns:
|
83
86
|
The run steps according to query filters.
|
84
87
|
"""
|
88
|
+
# A project scoped request must always be scoped to a specific
|
89
|
+
# project. This is required for the RBAC check to work.
|
90
|
+
set_filter_project_scope(step_run_filter_model)
|
91
|
+
assert isinstance(step_run_filter_model.project, UUID)
|
92
|
+
|
85
93
|
allowed_pipeline_run_ids = get_allowed_resource_ids(
|
86
|
-
resource_type=ResourceType.PIPELINE_RUN
|
94
|
+
resource_type=ResourceType.PIPELINE_RUN,
|
95
|
+
project_id=step_run_filter_model.project,
|
87
96
|
)
|
88
97
|
step_run_filter_model.configure_rbac(
|
89
98
|
authenticated_user_id=auth_context.user.id,
|
@@ -98,7 +107,6 @@ def list_run_steps(
|
|
98
107
|
|
99
108
|
@router.post(
|
100
109
|
"",
|
101
|
-
response_model=StepRunResponse,
|
102
110
|
responses={401: error_response, 409: error_response, 422: error_response},
|
103
111
|
)
|
104
112
|
@handle_exceptions
|
@@ -110,20 +118,22 @@ def create_run_step(
|
|
110
118
|
|
111
119
|
Args:
|
112
120
|
step: The run step to create.
|
121
|
+
_: Authentication context.
|
113
122
|
|
114
123
|
Returns:
|
115
124
|
The created run step.
|
116
125
|
"""
|
117
126
|
pipeline_run = zen_store().get_run(step.pipeline_run_id)
|
118
|
-
verify_permission_for_model(pipeline_run, action=Action.UPDATE)
|
119
127
|
|
120
|
-
|
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
|