zenml-nightly 0.58.2.dev20240623__py3-none-any.whl → 0.61.0.dev20240712__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.
- README.md +30 -9
- RELEASE_NOTES.md +240 -0
- zenml/VERSION +1 -1
- zenml/actions/base_action.py +177 -174
- zenml/actions/pipeline_run/pipeline_run_action.py +28 -23
- zenml/analytics/enums.py +3 -0
- zenml/artifact_stores/base_artifact_store.py +7 -1
- zenml/artifacts/utils.py +13 -10
- zenml/cli/__init__.py +28 -0
- zenml/cli/artifact.py +1 -2
- zenml/cli/integration.py +9 -8
- zenml/cli/server.py +6 -0
- zenml/cli/service_connectors.py +1 -0
- zenml/cli/stack.py +946 -39
- zenml/cli/stack_components.py +7 -0
- zenml/cli/text_utils.py +35 -1
- zenml/cli/utils.py +127 -10
- zenml/client.py +257 -72
- zenml/config/compiler.py +10 -9
- zenml/config/docker_settings.py +33 -14
- zenml/constants.py +11 -2
- zenml/container_registries/base_container_registry.py +1 -0
- zenml/enums.py +7 -0
- zenml/event_hub/base_event_hub.py +5 -5
- zenml/event_hub/event_hub.py +20 -14
- zenml/event_sources/base_event.py +0 -11
- zenml/event_sources/base_event_source.py +7 -0
- zenml/event_sources/webhooks/base_webhook_event_source.py +1 -4
- zenml/exceptions.py +4 -0
- zenml/hooks/hook_validators.py +2 -3
- zenml/integrations/aws/__init__.py +1 -0
- zenml/integrations/azure/__init__.py +1 -0
- zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +3 -3
- zenml/integrations/deepchecks/__init__.py +1 -0
- zenml/integrations/discord/__init__.py +1 -0
- zenml/integrations/evidently/__init__.py +1 -0
- zenml/integrations/facets/__init__.py +1 -0
- zenml/integrations/feast/__init__.py +1 -0
- zenml/integrations/gcp/__init__.py +3 -1
- zenml/integrations/gcp/google_credentials_mixin.py +1 -1
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +320 -64
- zenml/integrations/huggingface/__init__.py +1 -0
- zenml/integrations/integration.py +24 -0
- zenml/integrations/kubeflow/__init__.py +3 -0
- zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +1 -1
- zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +0 -1
- zenml/integrations/kubernetes/__init__.py +3 -1
- zenml/integrations/kubernetes/orchestrators/kube_utils.py +4 -1
- zenml/integrations/label_studio/annotators/label_studio_annotator.py +1 -0
- zenml/integrations/langchain/__init__.py +1 -0
- zenml/integrations/mlflow/__init__.py +4 -2
- zenml/integrations/neural_prophet/__init__.py +1 -0
- zenml/integrations/polars/__init__.py +1 -0
- zenml/integrations/prodigy/__init__.py +1 -0
- zenml/integrations/pycaret/__init__.py +6 -0
- zenml/integrations/registry.py +37 -0
- zenml/integrations/s3/artifact_stores/s3_artifact_store.py +93 -9
- zenml/integrations/seldon/__init__.py +1 -0
- zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -0
- zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +2 -2
- zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +1 -1
- zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py +2 -2
- zenml/integrations/skypilot_aws/__init__.py +2 -1
- zenml/integrations/skypilot_azure/__init__.py +1 -1
- zenml/integrations/skypilot_gcp/__init__.py +1 -1
- zenml/integrations/skypilot_lambda/__init__.py +1 -1
- zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +1 -1
- zenml/integrations/slack/__init__.py +1 -0
- zenml/integrations/tekton/__init__.py +1 -0
- zenml/integrations/tensorboard/__init__.py +0 -1
- zenml/integrations/tensorflow/__init__.py +18 -6
- zenml/integrations/wandb/__init__.py +1 -0
- zenml/logging/step_logging.py +54 -51
- zenml/models/__init__.py +28 -0
- zenml/models/v2/core/action.py +276 -0
- zenml/models/v2/core/component.py +18 -0
- zenml/models/v2/core/model.py +1 -2
- zenml/models/v2/core/service_connector.py +17 -0
- zenml/models/v2/core/stack.py +31 -0
- zenml/models/v2/core/trigger.py +182 -141
- zenml/models/v2/misc/full_stack.py +97 -0
- zenml/models/v2/misc/stack_deployment.py +86 -0
- zenml/new/pipelines/pipeline.py +14 -4
- zenml/new/pipelines/pipeline_decorator.py +1 -2
- zenml/new/pipelines/run_utils.py +1 -12
- zenml/new/steps/step_decorator.py +2 -3
- zenml/orchestrators/input_utils.py +3 -6
- zenml/pipelines/base_pipeline.py +0 -2
- zenml/pipelines/pipeline_decorator.py +1 -2
- zenml/stack/stack.py +3 -6
- zenml/stack/stack_component.py +4 -0
- zenml/stack_deployments/__init__.py +14 -0
- zenml/stack_deployments/aws_stack_deployment.py +254 -0
- zenml/stack_deployments/gcp_stack_deployment.py +260 -0
- zenml/stack_deployments/stack_deployment.py +208 -0
- zenml/stack_deployments/utils.py +44 -0
- zenml/steps/base_step.py +1 -2
- zenml/steps/step_decorator.py +1 -2
- zenml/types.py +10 -1
- zenml/utils/function_utils.py +1 -1
- zenml/utils/pagination_utils.py +7 -5
- zenml/utils/pipeline_docker_image_builder.py +117 -73
- zenml/utils/pydantic_utils.py +6 -5
- zenml/zen_server/cloud_utils.py +18 -3
- zenml/zen_server/dashboard/assets/{404-CDPQCl4D.js → 404-DpJaNHKF.js} +1 -1
- zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +85 -0
- zenml/zen_server/dashboard/assets/{@react-router-DYovave8.js → @react-router-CO-OsFwI.js} +2 -2
- zenml/zen_server/dashboard/assets/{@reactflow-CHBapDaj.js → @reactflow-DJfzkHO1.js} +2 -2
- zenml/zen_server/dashboard/assets/@tanstack-DYiOyJUL.js +22 -0
- zenml/zen_server/dashboard/assets/AwarenessChannel-BYDLT2xC.js +1 -0
- zenml/zen_server/dashboard/assets/{CodeSnippet-BidtnWOi.js → CodeSnippet-BkOuRmyq.js} +2 -2
- zenml/zen_server/dashboard/assets/Commands-ZvWR1BRs.js +1 -0
- zenml/zen_server/dashboard/assets/CopyButton-DVwLkafa.js +2 -0
- zenml/zen_server/dashboard/assets/{CsvVizualization-BOuez-fG.js → CsvVizualization-C2IiqX4I.js} +7 -7
- zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +1 -0
- zenml/zen_server/dashboard/assets/EmptyState-BMLnFVlB.js +1 -0
- zenml/zen_server/dashboard/assets/Error-CqX0VqW_.js +1 -0
- zenml/zen_server/dashboard/assets/ExecutionStatus-BoLUXR9t.js +1 -0
- zenml/zen_server/dashboard/assets/Helpbox-LFydyVwh.js +1 -0
- zenml/zen_server/dashboard/assets/Infobox-DnENC0sh.js +1 -0
- zenml/zen_server/dashboard/assets/InlineAvatar-CbJtYr0t.js +1 -0
- zenml/zen_server/dashboard/assets/{MarkdownVisualization-DsB2QZiK.js → MarkdownVisualization-xp3hhULl.js} +2 -2
- zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +1 -0
- zenml/zen_server/dashboard/assets/PasswordChecker-DUveqlva.js +1 -0
- zenml/zen_server/dashboard/assets/SetPassword-BYBdbQDo.js +1 -0
- zenml/zen_server/dashboard/assets/SuccessStep-Nx743hll.js +1 -0
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DnM-c11H.js → UpdatePasswordSchemas-DF9gSzE0.js} +1 -1
- zenml/zen_server/dashboard/assets/{aws-t0gKCj_R.js → aws-BgKTfTfx.js} +1 -1
- zenml/zen_server/dashboard/assets/{check-circle-BVvhm5dy.js → check-circle-i56092KI.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-down-zcvCWmyP.js → chevron-down-D_ZlKMqH.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-right-double-CJ50E9Gr.js → chevron-right-double-BiEMg7rd.js} +1 -1
- zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +1 -0
- zenml/zen_server/dashboard/assets/{copy-BRhQz3j-.js → copy-BXNk6BjL.js} +1 -1
- zenml/zen_server/dashboard/assets/{database-CRRnyFWh.js → database-1xWSgZfO.js} +1 -1
- zenml/zen_server/dashboard/assets/{docker-BAonhm6G.js → docker-CQMVm_4d.js} +1 -1
- zenml/zen_server/dashboard/assets/{file-text-CbVERUON.js → file-text-CqD_iu6l.js} +1 -1
- zenml/zen_server/dashboard/assets/{help-B8rqCvqn.js → help-bu_DgLKI.js} +1 -1
- zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +1 -0
- zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +55 -0
- zenml/zen_server/dashboard/assets/index-inApY3KQ.css +1 -0
- zenml/zen_server/dashboard/assets/index-rK_Wuy2W.js +1 -0
- zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +1 -0
- zenml/zen_server/dashboard/assets/{login-mutation-wzzl23C6.js → login-mutation-BUnVASxp.js} +1 -1
- zenml/zen_server/dashboard/assets/not-found-B4VnX8gK.js +1 -0
- zenml/zen_server/dashboard/assets/package-CsUhPmou.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BmkSiYeQ.js → page-3efNCDeb.js} +2 -2
- zenml/zen_server/dashboard/assets/page-7zTHbhhI.js +1 -0
- zenml/zen_server/dashboard/assets/page-BEs6jK71.js +1 -0
- zenml/zen_server/dashboard/assets/page-BpSqIf4B.js +1 -0
- zenml/zen_server/dashboard/assets/{page-AQKopn_4.js → page-Bx6o0ARS.js} +1 -1
- zenml/zen_server/dashboard/assets/page-C43QGHTt.js +9 -0
- zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +1 -0
- zenml/zen_server/dashboard/assets/page-CRTJ0UuR.js +1 -0
- zenml/zen_server/dashboard/assets/page-CUZIGO-3.js +1 -0
- zenml/zen_server/dashboard/assets/page-CaopxiU1.js +1 -0
- zenml/zen_server/dashboard/assets/{page-CuT1SUik.js → page-Cx67M0QT.js} +1 -1
- zenml/zen_server/dashboard/assets/page-D7Z399xy.js +1 -0
- zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BzVZGExK.js → page-DKlIdAe5.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Bi5AI0S7.js → page-DMOYZppS.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +2 -0
- zenml/zen_server/dashboard/assets/{page-BW6Ket3a.js → page-Dc_7KMQE.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DvCvroOM.js +1 -0
- zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +1 -0
- zenml/zen_server/dashboard/assets/page-JyfeDUfu.js +1 -0
- zenml/zen_server/dashboard/assets/{page-yN4rZ-ZS.js → page-Sxn82W-5.js} +1 -1
- zenml/zen_server/dashboard/assets/page-TKXERe16.js +1 -0
- zenml/zen_server/dashboard/assets/page-Xu8JEjSU.js +1 -0
- zenml/zen_server/dashboard/assets/{play-circle-DK5QMJyp.js → play-circle-CNtZKDnW.js} +1 -1
- zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +1 -0
- zenml/zen_server/dashboard/assets/{terminal-B2ovgWuz.js → terminal-By9cErXc.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-0Wgz8pUE.js → update-server-settings-mutation-CR8e3Sir.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-6_xv0WJS.js → url-DuQMeqYA.js} +1 -1
- zenml/zen_server/dashboard/assets/{zod-DrZvVLjd.js → zod-BhoGpZ63.js} +1 -1
- zenml/zen_server/dashboard/index.html +7 -7
- zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
- zenml/zen_server/dashboard_legacy/index.html +1 -1
- zenml/zen_server/dashboard_legacy/{precache-manifest.f4abc5b7cfa7d90c1caf5521918e29a8.js → precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js} +4 -4
- zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
- zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js → main.382439a7.chunk.js} +2 -2
- zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js.map → main.382439a7.chunk.js.map} +1 -1
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +11 -5
- zenml/zen_server/pipeline_deployment/utils.py +57 -44
- zenml/zen_server/rbac/models.py +1 -0
- zenml/zen_server/rbac/utils.py +22 -1
- zenml/zen_server/rbac/zenml_cloud_rbac.py +11 -5
- zenml/zen_server/routers/actions_endpoints.py +324 -0
- zenml/zen_server/routers/stack_deployment_endpoints.py +158 -0
- zenml/zen_server/routers/triggers_endpoints.py +30 -158
- zenml/zen_server/routers/workspaces_endpoints.py +64 -0
- zenml/zen_server/zen_server_api.py +4 -0
- zenml/zen_stores/migrations/utils.py +1 -1
- zenml/zen_stores/migrations/versions/0.60.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0.61.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
- zenml/zen_stores/migrations/versions/25155145c545_separate_actions_and_triggers.py +228 -0
- zenml/zen_stores/rest_zen_store.py +248 -8
- zenml/zen_stores/schemas/__init__.py +2 -0
- zenml/zen_stores/schemas/action_schemas.py +192 -0
- zenml/zen_stores/schemas/stack_schemas.py +10 -0
- zenml/zen_stores/schemas/step_run_schemas.py +27 -11
- zenml/zen_stores/schemas/trigger_schemas.py +43 -50
- zenml/zen_stores/schemas/user_schemas.py +10 -2
- zenml/zen_stores/schemas/workspace_schemas.py +5 -0
- zenml/zen_stores/sql_zen_store.py +540 -36
- zenml/zen_stores/zen_store_interface.py +165 -0
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/METADATA +33 -11
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/RECORD +213 -193
- zenml/zen_server/dashboard/assets/@radix-C9DBgJhe.js +0 -77
- zenml/zen_server/dashboard/assets/@tanstack-CEbkxrhX.js +0 -30
- zenml/zen_server/dashboard/assets/AwarenessChannel-nXGpmj_f.js +0 -1
- zenml/zen_server/dashboard/assets/Cards-nwsvQLVS.js +0 -1
- zenml/zen_server/dashboard/assets/Commands-DuIWKg_Q.js +0 -1
- zenml/zen_server/dashboard/assets/CopyButton-B_YSm-Ds.js +0 -2
- zenml/zen_server/dashboard/assets/DisplayDate-BdguISQF.js +0 -1
- zenml/zen_server/dashboard/assets/EmptyState-BkooiGtL.js +0 -1
- zenml/zen_server/dashboard/assets/Error-B6M0dPph.js +0 -1
- zenml/zen_server/dashboard/assets/Helpbox-BQoqCm04.js +0 -1
- zenml/zen_server/dashboard/assets/Infobox-Ce9mefqU.js +0 -1
- zenml/zen_server/dashboard/assets/InlineAvatar-DGf3dVhV.js +0 -1
- zenml/zen_server/dashboard/assets/PageHeader-DGaemzjc.js +0 -1
- zenml/zen_server/dashboard/assets/Pagination-DVYfBCCc.js +0 -1
- zenml/zen_server/dashboard/assets/PasswordChecker-DSLBp7Vl.js +0 -1
- zenml/zen_server/dashboard/assets/SetPassword-B5s7DJug.js +0 -1
- zenml/zen_server/dashboard/assets/SuccessStep-ZzczaM7g.js +0 -1
- zenml/zen_server/dashboard/assets/cloud-only-Ba_ShBR5.js +0 -1
- zenml/zen_server/dashboard/assets/index-CWJ3xbIf.css +0 -1
- zenml/zen_server/dashboard/assets/index-QORVVTMN.js +0 -55
- zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +0 -1
- zenml/zen_server/dashboard/assets/not-found-Dh2la7kh.js +0 -1
- zenml/zen_server/dashboard/assets/page-B-5jAKoO.js +0 -1
- zenml/zen_server/dashboard/assets/page-B-vWk8a6.js +0 -1
- zenml/zen_server/dashboard/assets/page-B0BrqfS8.js +0 -1
- zenml/zen_server/dashboard/assets/page-BQxVFlUl.js +0 -1
- zenml/zen_server/dashboard/assets/page-ByrHy6Ss.js +0 -1
- zenml/zen_server/dashboard/assets/page-CPtY4Kv_.js +0 -1
- zenml/zen_server/dashboard/assets/page-CmmukLsl.js +0 -1
- zenml/zen_server/dashboard/assets/page-D2D-7qyr.js +0 -9
- zenml/zen_server/dashboard/assets/page-DAQQyLxT.js +0 -1
- zenml/zen_server/dashboard/assets/page-DHkUMl_E.js +0 -1
- zenml/zen_server/dashboard/assets/page-DZCbwOEs.js +0 -2
- zenml/zen_server/dashboard/assets/page-DdaIt20-.js +0 -1
- zenml/zen_server/dashboard/assets/page-LqLs24Ot.js +0 -1
- zenml/zen_server/dashboard/assets/page-lebv0c7C.js +0 -1
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/entry_points.txt +0 -0
@@ -20,8 +20,8 @@ ZenML is an open-source MLOps framework designed to help you create robust, main
|
|
20
20
|
To install the ZenML chart directly from Amazon ECR, use the following command:
|
21
21
|
|
22
22
|
```bash
|
23
|
-
# example command for version 0.
|
24
|
-
helm install my-zenml oci://public.ecr.aws/zenml/zenml --version 0.
|
23
|
+
# example command for version 0.61.0
|
24
|
+
helm install my-zenml oci://public.ecr.aws/zenml/zenml --version 0.61.0
|
25
25
|
```
|
26
26
|
|
27
27
|
Note: Ensure you have OCI support enabled in your Helm client and that you are authenticated with Amazon ECR.
|
@@ -21,7 +21,7 @@ from pydantic import BaseModel, Field
|
|
21
21
|
from zenml.config.server_config import ServerConfiguration
|
22
22
|
from zenml.exceptions import SubscriptionUpgradeRequiredError
|
23
23
|
from zenml.logger import get_logger
|
24
|
-
from zenml.zen_server.cloud_utils import
|
24
|
+
from zenml.zen_server.cloud_utils import cloud_connection
|
25
25
|
from zenml.zen_server.feature_gate.feature_gate_interface import (
|
26
26
|
FeatureGateInterface,
|
27
27
|
)
|
@@ -59,8 +59,12 @@ class RawUsageEvent(BaseModel):
|
|
59
59
|
)
|
60
60
|
|
61
61
|
|
62
|
-
class ZenMLCloudFeatureGateInterface(FeatureGateInterface
|
63
|
-
"""Feature Gate
|
62
|
+
class ZenMLCloudFeatureGateInterface(FeatureGateInterface):
|
63
|
+
"""ZenML Cloud Feature Gate implementation."""
|
64
|
+
|
65
|
+
def __init__(self) -> None:
|
66
|
+
"""Initialize the object."""
|
67
|
+
self._connection = cloud_connection()
|
64
68
|
|
65
69
|
def check_entitlement(self, resource: ResourceType) -> None:
|
66
70
|
"""Checks if a user is entitled to create a resource.
|
@@ -72,7 +76,7 @@ class ZenMLCloudFeatureGateInterface(FeatureGateInterface, ZenMLCloudSession):
|
|
72
76
|
SubscriptionUpgradeRequiredError: in case a subscription limit is reached
|
73
77
|
"""
|
74
78
|
try:
|
75
|
-
response = self.
|
79
|
+
response = self._connection.get(
|
76
80
|
endpoint=ENTITLEMENT_ENDPOINT + "/" + resource, params=None
|
77
81
|
)
|
78
82
|
except SubscriptionUpgradeRequiredError:
|
@@ -110,7 +114,9 @@ class ZenMLCloudFeatureGateInterface(FeatureGateInterface, ZenMLCloudSession):
|
|
110
114
|
"resource_id": str(resource_id),
|
111
115
|
},
|
112
116
|
).model_dump()
|
113
|
-
response = self.
|
117
|
+
response = self._connection.post(
|
118
|
+
endpoint=USAGE_EVENT_ENDPOINT, data=data
|
119
|
+
)
|
114
120
|
if response.status_code != 200:
|
115
121
|
logger.error(
|
116
122
|
"Usage report not accepted by upstream backend. "
|
@@ -17,7 +17,7 @@ from zenml.constants import (
|
|
17
17
|
ENV_ZENML_ACTIVE_STACK_ID,
|
18
18
|
ENV_ZENML_ACTIVE_WORKSPACE_ID,
|
19
19
|
)
|
20
|
-
from zenml.enums import StackComponentType, StoreType
|
20
|
+
from zenml.enums import ExecutionStatus, StackComponentType, StoreType
|
21
21
|
from zenml.integrations.utils import get_integration_for_module
|
22
22
|
from zenml.models import (
|
23
23
|
CodeReferenceRequest,
|
@@ -26,6 +26,7 @@ from zenml.models import (
|
|
26
26
|
PipelineDeploymentRequest,
|
27
27
|
PipelineDeploymentResponse,
|
28
28
|
PipelineRunResponse,
|
29
|
+
PipelineRunUpdate,
|
29
30
|
StackResponse,
|
30
31
|
)
|
31
32
|
from zenml.new.pipelines.run_utils import (
|
@@ -88,8 +89,6 @@ def run_pipeline(
|
|
88
89
|
ensure_async_orchestrator(deployment=deployment_request, stack=stack)
|
89
90
|
|
90
91
|
new_deployment = zen_store().create_deployment(deployment_request)
|
91
|
-
placeholder_run = create_placeholder_run(deployment=new_deployment)
|
92
|
-
assert placeholder_run
|
93
92
|
|
94
93
|
if auth_context.access_token:
|
95
94
|
token = auth_context.access_token
|
@@ -125,52 +124,62 @@ def run_pipeline(
|
|
125
124
|
deployment_id=new_deployment.id
|
126
125
|
)
|
127
126
|
|
128
|
-
|
129
|
-
|
130
|
-
stack=stack
|
131
|
-
)
|
127
|
+
placeholder_run = create_placeholder_run(deployment=new_deployment)
|
128
|
+
assert placeholder_run
|
132
129
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
python_version = (
|
138
|
-
f"{sys.version_info.major}.{sys.version_info.minor}"
|
130
|
+
def _task() -> None:
|
131
|
+
try:
|
132
|
+
pypi_requirements, apt_packages = get_requirements_for_stack(
|
133
|
+
stack=stack
|
139
134
|
)
|
140
135
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
136
|
+
if build.python_version:
|
137
|
+
version_info = version.parse(build.python_version)
|
138
|
+
python_version = f"{version_info.major}.{version_info.minor}"
|
139
|
+
else:
|
140
|
+
python_version = (
|
141
|
+
f"{sys.version_info.major}.{sys.version_info.minor}"
|
142
|
+
)
|
143
|
+
|
144
|
+
dockerfile = generate_dockerfile(
|
145
|
+
pypi_requirements=pypi_requirements,
|
146
|
+
apt_packages=apt_packages,
|
147
|
+
zenml_version=zenml_version,
|
148
|
+
python_version=python_version,
|
149
|
+
)
|
147
150
|
|
148
|
-
|
151
|
+
image_hash = generate_image_hash(dockerfile=dockerfile)
|
149
152
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
153
|
+
runner_image = workload_manager().build_and_push_image(
|
154
|
+
workload_id=new_deployment.id,
|
155
|
+
dockerfile=dockerfile,
|
156
|
+
image_name=f"{RUNNER_IMAGE_REPOSITORY}:{image_hash}",
|
157
|
+
sync=True,
|
158
|
+
)
|
156
159
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
160
|
+
workload_manager().log(
|
161
|
+
workload_id=new_deployment.id,
|
162
|
+
message="Starting pipeline deployment.",
|
163
|
+
)
|
164
|
+
workload_manager().run(
|
165
|
+
workload_id=new_deployment.id,
|
166
|
+
image=runner_image,
|
167
|
+
command=command,
|
168
|
+
arguments=args,
|
169
|
+
environment=environment,
|
170
|
+
timeout_in_seconds=30,
|
171
|
+
sync=True,
|
172
|
+
)
|
173
|
+
workload_manager().log(
|
174
|
+
workload_id=new_deployment.id,
|
175
|
+
message="Pipeline deployed successfully.",
|
176
|
+
)
|
177
|
+
except Exception:
|
178
|
+
zen_store().update_run(
|
179
|
+
run_id=placeholder_run.id,
|
180
|
+
run_update=PipelineRunUpdate(status=ExecutionStatus.FAILED),
|
181
|
+
)
|
182
|
+
raise
|
174
183
|
|
175
184
|
if background_tasks:
|
176
185
|
background_tasks.add_task(_task)
|
@@ -357,8 +366,12 @@ def apply_run_config(
|
|
357
366
|
step_config = StepConfiguration.model_validate(step_config_dict)
|
358
367
|
|
359
368
|
if update := run_config.steps.get(invocation_id):
|
369
|
+
update_dict = update.model_dump()
|
370
|
+
# Get rid of deprecated name to prevent overriding the step name
|
371
|
+
# with `None`.
|
372
|
+
update_dict.pop("name", None)
|
360
373
|
step_config = pydantic_utils.update_model(
|
361
|
-
step_config, update=
|
374
|
+
step_config, update=update_dict
|
362
375
|
)
|
363
376
|
steps[invocation_id] = Step(spec=step.spec, config=step_config)
|
364
377
|
|
zenml/zen_server/rbac/models.py
CHANGED
zenml/zen_server/rbac/utils.py
CHANGED
@@ -189,7 +189,12 @@ def get_permission_denied_model(model: AnyResponse) -> AnyResponse:
|
|
189
189
|
The permission denied model.
|
190
190
|
"""
|
191
191
|
return model.model_copy(
|
192
|
-
update={
|
192
|
+
update={
|
193
|
+
"body": None,
|
194
|
+
"metadata": None,
|
195
|
+
"resources": None,
|
196
|
+
"permission_denied": True,
|
197
|
+
}
|
193
198
|
)
|
194
199
|
|
195
200
|
|
@@ -384,10 +389,12 @@ def get_resource_type_for_model(
|
|
384
389
|
is not associated with any resource type.
|
385
390
|
"""
|
386
391
|
from zenml.models import (
|
392
|
+
ActionResponse,
|
387
393
|
ArtifactResponse,
|
388
394
|
ArtifactVersionResponse,
|
389
395
|
CodeRepositoryResponse,
|
390
396
|
ComponentResponse,
|
397
|
+
EventSourceResponse,
|
391
398
|
FlavorResponse,
|
392
399
|
ModelResponse,
|
393
400
|
ModelVersionResponse,
|
@@ -402,6 +409,8 @@ def get_resource_type_for_model(
|
|
402
409
|
ServiceResponse,
|
403
410
|
StackResponse,
|
404
411
|
TagResponse,
|
412
|
+
TriggerExecutionResponse,
|
413
|
+
TriggerResponse,
|
405
414
|
UserResponse,
|
406
415
|
WorkspaceResponse,
|
407
416
|
)
|
@@ -410,6 +419,8 @@ def get_resource_type_for_model(
|
|
410
419
|
Any,
|
411
420
|
ResourceType,
|
412
421
|
] = {
|
422
|
+
ActionResponse: ResourceType.ACTION,
|
423
|
+
EventSourceResponse: ResourceType.EVENT_SOURCE,
|
413
424
|
FlavorResponse: ResourceType.FLAVOR,
|
414
425
|
ServiceConnectorResponse: ResourceType.SERVICE_CONNECTOR,
|
415
426
|
ComponentResponse: ResourceType.STACK_COMPONENT,
|
@@ -428,6 +439,8 @@ def get_resource_type_for_model(
|
|
428
439
|
PipelineBuildResponse: ResourceType.PIPELINE_BUILD,
|
429
440
|
PipelineRunResponse: ResourceType.PIPELINE_RUN,
|
430
441
|
TagResponse: ResourceType.TAG,
|
442
|
+
TriggerResponse: ResourceType.TRIGGER,
|
443
|
+
TriggerExecutionResponse: ResourceType.TRIGGER_EXECUTION,
|
431
444
|
ServiceAccountResponse: ResourceType.SERVICE_ACCOUNT,
|
432
445
|
ServiceResponse: ResourceType.SERVICE,
|
433
446
|
}
|
@@ -522,9 +535,11 @@ def get_schema_for_resource_type(
|
|
522
535
|
The database schema.
|
523
536
|
"""
|
524
537
|
from zenml.zen_stores.schemas import (
|
538
|
+
ActionSchema,
|
525
539
|
ArtifactSchema,
|
526
540
|
ArtifactVersionSchema,
|
527
541
|
CodeRepositorySchema,
|
542
|
+
EventSourceSchema,
|
528
543
|
FlavorSchema,
|
529
544
|
ModelSchema,
|
530
545
|
ModelVersionSchema,
|
@@ -539,6 +554,8 @@ def get_schema_for_resource_type(
|
|
539
554
|
StackComponentSchema,
|
540
555
|
StackSchema,
|
541
556
|
TagSchema,
|
557
|
+
TriggerExecutionSchema,
|
558
|
+
TriggerSchema,
|
542
559
|
UserSchema,
|
543
560
|
WorkspaceSchema,
|
544
561
|
)
|
@@ -564,6 +581,10 @@ def get_schema_for_resource_type(
|
|
564
581
|
ResourceType.PIPELINE_BUILD: PipelineBuildSchema,
|
565
582
|
ResourceType.RUN_METADATA: RunMetadataSchema,
|
566
583
|
ResourceType.USER: UserSchema,
|
584
|
+
ResourceType.ACTION: ActionSchema,
|
585
|
+
ResourceType.EVENT_SOURCE: EventSourceSchema,
|
586
|
+
ResourceType.TRIGGER: TriggerSchema,
|
587
|
+
ResourceType.TRIGGER_EXECUTION: TriggerExecutionSchema,
|
567
588
|
}
|
568
589
|
|
569
590
|
return mapping[resource_type]
|
@@ -15,7 +15,7 @@
|
|
15
15
|
|
16
16
|
from typing import TYPE_CHECKING, Dict, List, Set, Tuple
|
17
17
|
|
18
|
-
from zenml.zen_server.cloud_utils import
|
18
|
+
from zenml.zen_server.cloud_utils import cloud_connection
|
19
19
|
from zenml.zen_server.rbac.models import Action, Resource
|
20
20
|
from zenml.zen_server.rbac.rbac_interface import RBACInterface
|
21
21
|
from zenml.zen_server.utils import server_config
|
@@ -74,9 +74,13 @@ def _convert_from_cloud_resource(cloud_resource: str) -> Resource:
|
|
74
74
|
return Resource(type=resource_type_and_id)
|
75
75
|
|
76
76
|
|
77
|
-
class ZenMLCloudRBAC(RBACInterface
|
77
|
+
class ZenMLCloudRBAC(RBACInterface):
|
78
78
|
"""RBAC implementation that uses the ZenML Pro Management Plane as a backend."""
|
79
79
|
|
80
|
+
def __init__(self) -> None:
|
81
|
+
"""Initialize the object."""
|
82
|
+
self._connection = cloud_connection()
|
83
|
+
|
80
84
|
def check_permissions(
|
81
85
|
self, user: "UserResponse", resources: Set[Resource], action: Action
|
82
86
|
) -> Dict[Resource, bool]:
|
@@ -110,7 +114,9 @@ class ZenMLCloudRBAC(RBACInterface, ZenMLCloudSession):
|
|
110
114
|
],
|
111
115
|
"action": str(action),
|
112
116
|
}
|
113
|
-
response = self.
|
117
|
+
response = self._connection.get(
|
118
|
+
endpoint=PERMISSIONS_ENDPOINT, params=params
|
119
|
+
)
|
114
120
|
value = response.json()
|
115
121
|
|
116
122
|
assert isinstance(value, dict)
|
@@ -147,7 +153,7 @@ class ZenMLCloudRBAC(RBACInterface, ZenMLCloudSession):
|
|
147
153
|
"resource": _convert_to_cloud_resource(resource),
|
148
154
|
"action": str(action),
|
149
155
|
}
|
150
|
-
response = self.
|
156
|
+
response = self._connection.get(
|
151
157
|
endpoint=ALLOWED_RESOURCE_IDS_ENDPOINT, params=params
|
152
158
|
)
|
153
159
|
response_json = response.json()
|
@@ -177,4 +183,4 @@ class ZenMLCloudRBAC(RBACInterface, ZenMLCloudSession):
|
|
177
183
|
"resource": _convert_to_cloud_resource(resource),
|
178
184
|
"actions": [str(action) for action in actions],
|
179
185
|
}
|
180
|
-
self.
|
186
|
+
self._connection.post(endpoint=RESOURCE_MEMBERSHIP_ENDPOINT, data=data)
|
@@ -0,0 +1,324 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2024. 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 actions."""
|
15
|
+
|
16
|
+
from uuid import UUID
|
17
|
+
|
18
|
+
from fastapi import APIRouter, Depends, Security
|
19
|
+
|
20
|
+
from zenml import ActionRequest
|
21
|
+
from zenml.actions.base_action import BaseActionHandler
|
22
|
+
from zenml.constants import (
|
23
|
+
ACTIONS,
|
24
|
+
API,
|
25
|
+
VERSION_1,
|
26
|
+
)
|
27
|
+
from zenml.enums import PluginType
|
28
|
+
from zenml.models import (
|
29
|
+
ActionFilter,
|
30
|
+
ActionResponse,
|
31
|
+
ActionUpdate,
|
32
|
+
Page,
|
33
|
+
)
|
34
|
+
from zenml.zen_server.auth import AuthContext, authorize
|
35
|
+
from zenml.zen_server.exceptions import error_response
|
36
|
+
from zenml.zen_server.rbac.endpoint_utils import (
|
37
|
+
verify_permissions_and_create_entity,
|
38
|
+
verify_permissions_and_list_entities,
|
39
|
+
)
|
40
|
+
from zenml.zen_server.rbac.models import Action, ResourceType
|
41
|
+
from zenml.zen_server.rbac.utils import (
|
42
|
+
dehydrate_response_model,
|
43
|
+
verify_permission_for_model,
|
44
|
+
)
|
45
|
+
from zenml.zen_server.utils import (
|
46
|
+
handle_exceptions,
|
47
|
+
make_dependable,
|
48
|
+
plugin_flavor_registry,
|
49
|
+
zen_store,
|
50
|
+
)
|
51
|
+
|
52
|
+
router = APIRouter(
|
53
|
+
prefix=API + VERSION_1 + ACTIONS,
|
54
|
+
tags=["actions"],
|
55
|
+
responses={401: error_response, 403: error_response},
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
@router.get(
|
60
|
+
"",
|
61
|
+
response_model=Page[ActionResponse],
|
62
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
63
|
+
)
|
64
|
+
@handle_exceptions
|
65
|
+
def list_actions(
|
66
|
+
action_filter_model: ActionFilter = Depends(make_dependable(ActionFilter)),
|
67
|
+
hydrate: bool = False,
|
68
|
+
_: AuthContext = Security(authorize),
|
69
|
+
) -> Page[ActionResponse]:
|
70
|
+
"""List actions.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
action_filter_model: Filter model used for pagination, sorting,
|
74
|
+
filtering.
|
75
|
+
hydrate: Flag deciding whether to hydrate the output model(s)
|
76
|
+
by including metadata fields in the response.
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
Page of actions.
|
80
|
+
"""
|
81
|
+
|
82
|
+
def list_actions_fn(
|
83
|
+
filter_model: ActionFilter,
|
84
|
+
) -> Page[ActionResponse]:
|
85
|
+
"""List actions through their associated plugins.
|
86
|
+
|
87
|
+
Args:
|
88
|
+
filter_model: Filter model used for pagination, sorting,
|
89
|
+
filtering.
|
90
|
+
|
91
|
+
Raises:
|
92
|
+
ValueError: If the action handler for flavor/type is not valid.
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
All actions.
|
96
|
+
"""
|
97
|
+
actions = zen_store().list_actions(
|
98
|
+
action_filter_model=filter_model, hydrate=hydrate
|
99
|
+
)
|
100
|
+
|
101
|
+
# Process the actions through their associated plugins
|
102
|
+
for idx, action in enumerate(actions.items):
|
103
|
+
action_handler = plugin_flavor_registry().get_plugin(
|
104
|
+
name=action.flavor,
|
105
|
+
_type=PluginType.ACTION,
|
106
|
+
subtype=action.plugin_subtype,
|
107
|
+
)
|
108
|
+
|
109
|
+
# Validate that the flavor and plugin_type correspond to an action
|
110
|
+
# handler implementation
|
111
|
+
if not isinstance(action_handler, BaseActionHandler):
|
112
|
+
raise ValueError(
|
113
|
+
f"Action handler plugin {action.plugin_subtype} "
|
114
|
+
f"for flavor {action.flavor} is not a valid action "
|
115
|
+
"handler plugin."
|
116
|
+
)
|
117
|
+
|
118
|
+
actions.items[idx] = action_handler.get_action(
|
119
|
+
action, hydrate=hydrate
|
120
|
+
)
|
121
|
+
|
122
|
+
return actions
|
123
|
+
|
124
|
+
return verify_permissions_and_list_entities(
|
125
|
+
filter_model=action_filter_model,
|
126
|
+
resource_type=ResourceType.ACTION,
|
127
|
+
list_method=list_actions_fn,
|
128
|
+
)
|
129
|
+
|
130
|
+
|
131
|
+
@router.get(
|
132
|
+
"/{action_id}",
|
133
|
+
response_model=ActionResponse,
|
134
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
135
|
+
)
|
136
|
+
@handle_exceptions
|
137
|
+
def get_action(
|
138
|
+
action_id: UUID,
|
139
|
+
hydrate: bool = True,
|
140
|
+
_: AuthContext = Security(authorize),
|
141
|
+
) -> ActionResponse:
|
142
|
+
"""Returns the requested action.
|
143
|
+
|
144
|
+
Args:
|
145
|
+
action_id: ID of the action.
|
146
|
+
hydrate: Flag deciding whether to hydrate the output model(s)
|
147
|
+
by including metadata fields in the response.
|
148
|
+
|
149
|
+
Raises:
|
150
|
+
ValueError: If the action handler for flavor/type is not valid.
|
151
|
+
|
152
|
+
Returns:
|
153
|
+
The requested action.
|
154
|
+
"""
|
155
|
+
action = zen_store().get_action(action_id=action_id, hydrate=hydrate)
|
156
|
+
|
157
|
+
verify_permission_for_model(action, action=Action.READ)
|
158
|
+
|
159
|
+
action_handler = plugin_flavor_registry().get_plugin(
|
160
|
+
name=action.flavor,
|
161
|
+
_type=PluginType.ACTION,
|
162
|
+
subtype=action.plugin_subtype,
|
163
|
+
)
|
164
|
+
|
165
|
+
# Validate that the flavor and plugin_type correspond to an action
|
166
|
+
# handler implementation
|
167
|
+
if not isinstance(action_handler, BaseActionHandler):
|
168
|
+
raise ValueError(
|
169
|
+
f"Action handler plugin {action.plugin_subtype} "
|
170
|
+
f"for flavor {action.flavor} is not a valid action "
|
171
|
+
"handler plugin."
|
172
|
+
)
|
173
|
+
|
174
|
+
action = action_handler.get_action(action, hydrate=hydrate)
|
175
|
+
|
176
|
+
return dehydrate_response_model(action)
|
177
|
+
|
178
|
+
|
179
|
+
@router.post(
|
180
|
+
"",
|
181
|
+
response_model=ActionResponse,
|
182
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
183
|
+
)
|
184
|
+
@handle_exceptions
|
185
|
+
def create_action(
|
186
|
+
action: ActionRequest,
|
187
|
+
_: AuthContext = Security(authorize),
|
188
|
+
) -> ActionResponse:
|
189
|
+
"""Creates an action.
|
190
|
+
|
191
|
+
Args:
|
192
|
+
action: Action to create.
|
193
|
+
|
194
|
+
Raises:
|
195
|
+
ValueError: If the action handler for flavor/type is not valid.
|
196
|
+
|
197
|
+
Returns:
|
198
|
+
The created action.
|
199
|
+
"""
|
200
|
+
service_account = zen_store().get_service_account(
|
201
|
+
service_account_name_or_id=action.service_account_id
|
202
|
+
)
|
203
|
+
verify_permission_for_model(service_account, action=Action.READ)
|
204
|
+
|
205
|
+
action_handler = plugin_flavor_registry().get_plugin(
|
206
|
+
name=action.flavor,
|
207
|
+
_type=PluginType.ACTION,
|
208
|
+
subtype=action.plugin_subtype,
|
209
|
+
)
|
210
|
+
|
211
|
+
# Validate that the flavor and plugin_type correspond to an action
|
212
|
+
# handler implementation
|
213
|
+
if not isinstance(action_handler, BaseActionHandler):
|
214
|
+
raise ValueError(
|
215
|
+
f"Action handler plugin {action.plugin_subtype} "
|
216
|
+
f"for flavor {action.flavor} is not a valid action "
|
217
|
+
"handler plugin."
|
218
|
+
)
|
219
|
+
|
220
|
+
return verify_permissions_and_create_entity(
|
221
|
+
request_model=action,
|
222
|
+
resource_type=ResourceType.ACTION,
|
223
|
+
create_method=action_handler.create_action,
|
224
|
+
)
|
225
|
+
|
226
|
+
|
227
|
+
@router.put(
|
228
|
+
"/{action_id}",
|
229
|
+
response_model=ActionResponse,
|
230
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
231
|
+
)
|
232
|
+
@handle_exceptions
|
233
|
+
def update_action(
|
234
|
+
action_id: UUID,
|
235
|
+
action_update: ActionUpdate,
|
236
|
+
_: AuthContext = Security(authorize),
|
237
|
+
) -> ActionResponse:
|
238
|
+
"""Update an action.
|
239
|
+
|
240
|
+
Args:
|
241
|
+
action_id: ID of the action to update.
|
242
|
+
action_update: The action update.
|
243
|
+
|
244
|
+
Raises:
|
245
|
+
ValueError: If the action handler for flavor/type is not valid.
|
246
|
+
|
247
|
+
Returns:
|
248
|
+
The updated action.
|
249
|
+
"""
|
250
|
+
action = zen_store().get_action(action_id=action_id)
|
251
|
+
|
252
|
+
verify_permission_for_model(action, action=Action.UPDATE)
|
253
|
+
|
254
|
+
if action_update.service_account_id:
|
255
|
+
service_account = zen_store().get_service_account(
|
256
|
+
service_account_name_or_id=action_update.service_account_id
|
257
|
+
)
|
258
|
+
verify_permission_for_model(service_account, action=Action.READ)
|
259
|
+
|
260
|
+
action_handler = plugin_flavor_registry().get_plugin(
|
261
|
+
name=action.flavor,
|
262
|
+
_type=PluginType.ACTION,
|
263
|
+
subtype=action.plugin_subtype,
|
264
|
+
)
|
265
|
+
|
266
|
+
# Validate that the flavor and plugin_type correspond to an action
|
267
|
+
# handler implementation
|
268
|
+
if not isinstance(action_handler, BaseActionHandler):
|
269
|
+
raise ValueError(
|
270
|
+
f"Action handler plugin {action.plugin_subtype} "
|
271
|
+
f"for flavor {action.flavor} is not a valid action "
|
272
|
+
"handler plugin."
|
273
|
+
)
|
274
|
+
|
275
|
+
updated_action = action_handler.update_action(
|
276
|
+
action=action,
|
277
|
+
action_update=action_update,
|
278
|
+
)
|
279
|
+
|
280
|
+
return dehydrate_response_model(updated_action)
|
281
|
+
|
282
|
+
|
283
|
+
@router.delete(
|
284
|
+
"/{action_id}",
|
285
|
+
responses={401: error_response, 404: error_response, 422: error_response},
|
286
|
+
)
|
287
|
+
@handle_exceptions
|
288
|
+
def delete_action(
|
289
|
+
action_id: UUID,
|
290
|
+
force: bool = False,
|
291
|
+
_: AuthContext = Security(authorize),
|
292
|
+
) -> None:
|
293
|
+
"""Delete an action.
|
294
|
+
|
295
|
+
Args:
|
296
|
+
action_id: ID of the action.
|
297
|
+
force: Flag deciding whether to force delete the action.
|
298
|
+
|
299
|
+
Raises:
|
300
|
+
ValueError: If the action handler for flavor/type is not valid.
|
301
|
+
"""
|
302
|
+
action = zen_store().get_action(action_id=action_id)
|
303
|
+
|
304
|
+
verify_permission_for_model(action, action=Action.DELETE)
|
305
|
+
|
306
|
+
action_handler = plugin_flavor_registry().get_plugin(
|
307
|
+
name=action.flavor,
|
308
|
+
_type=PluginType.ACTION,
|
309
|
+
subtype=action.plugin_subtype,
|
310
|
+
)
|
311
|
+
|
312
|
+
# Validate that the flavor and plugin_type correspond to an action
|
313
|
+
# handler implementation
|
314
|
+
if not isinstance(action_handler, BaseActionHandler):
|
315
|
+
raise ValueError(
|
316
|
+
f"Action handler plugin {action.plugin_subtype} "
|
317
|
+
f"for flavor {action.flavor} is not a valid action "
|
318
|
+
"handler plugin."
|
319
|
+
)
|
320
|
+
|
321
|
+
action_handler.delete_action(
|
322
|
+
action=action,
|
323
|
+
force=force,
|
324
|
+
)
|