zenml-nightly 0.58.2.dev20240626__py3-none-any.whl → 0.62.0.dev20240726__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 +31 -10
- RELEASE_NOTES.md +280 -0
- zenml/VERSION +1 -1
- zenml/__init__.py +2 -0
- zenml/analytics/enums.py +3 -0
- 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/stack.py +812 -39
- zenml/cli/stack_components.py +9 -0
- zenml/cli/text_utils.py +35 -1
- zenml/cli/utils.py +127 -10
- zenml/client.py +23 -14
- zenml/config/docker_settings.py +8 -5
- zenml/constants.py +13 -1
- zenml/container_registries/base_container_registry.py +1 -0
- zenml/enums.py +23 -0
- zenml/event_hub/event_hub.py +5 -8
- zenml/integrations/__init__.py +1 -0
- zenml/integrations/aws/__init__.py +1 -0
- zenml/integrations/azure/__init__.py +3 -2
- zenml/integrations/constants.py +1 -0
- zenml/integrations/databricks/__init__.py +52 -0
- zenml/integrations/databricks/flavors/__init__.py +30 -0
- zenml/integrations/databricks/flavors/databricks_model_deployer_flavor.py +118 -0
- zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +147 -0
- zenml/integrations/databricks/model_deployers/__init__.py +20 -0
- zenml/integrations/databricks/model_deployers/databricks_model_deployer.py +249 -0
- zenml/integrations/databricks/orchestrators/__init__.py +20 -0
- zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +497 -0
- zenml/integrations/databricks/orchestrators/databricks_orchestrator_entrypoint_config.py +97 -0
- zenml/integrations/databricks/services/__init__.py +19 -0
- zenml/integrations/databricks/services/databricks_deployment.py +407 -0
- zenml/integrations/databricks/utils/__init__.py +14 -0
- zenml/integrations/databricks/utils/databricks_utils.py +87 -0
- 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/great_expectations/data_validators/ge_data_validator.py +12 -8
- zenml/integrations/huggingface/__init__.py +1 -0
- zenml/integrations/huggingface/materializers/huggingface_datasets_materializer.py +88 -3
- zenml/integrations/huggingface/steps/accelerate_runner.py +1 -7
- 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/kubernetes/orchestrators/kubernetes_orchestrator.py +1 -13
- zenml/integrations/kubernetes/orchestrators/manifest_utils.py +22 -4
- zenml/integrations/kubernetes/pod_settings.py +4 -0
- zenml/integrations/label_studio/annotators/label_studio_annotator.py +1 -0
- zenml/integrations/langchain/__init__.py +1 -0
- zenml/integrations/lightgbm/__init__.py +1 -0
- zenml/integrations/mlflow/__init__.py +4 -2
- zenml/integrations/mlflow/model_registries/mlflow_model_registry.py +6 -2
- zenml/integrations/mlflow/services/mlflow_deployment.py +1 -1
- 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 +17 -6
- 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 -3
- 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 +34 -35
- zenml/materializers/built_in_materializer.py +1 -1
- zenml/materializers/cloudpickle_materializer.py +1 -1
- zenml/model/model.py +1 -1
- zenml/models/__init__.py +11 -0
- zenml/models/v2/core/component.py +47 -0
- zenml/models/v2/core/model.py +1 -2
- zenml/models/v2/core/server_settings.py +0 -20
- zenml/models/v2/core/service_connector.py +17 -0
- zenml/models/v2/core/stack.py +31 -0
- zenml/models/v2/misc/full_stack.py +129 -0
- zenml/models/v2/misc/stack_deployment.py +91 -0
- zenml/new/pipelines/pipeline.py +1 -1
- zenml/new/pipelines/run_utils.py +1 -1
- zenml/orchestrators/__init__.py +4 -0
- zenml/orchestrators/input_utils.py +3 -6
- zenml/orchestrators/step_launcher.py +1 -0
- zenml/orchestrators/wheeled_orchestrator.py +147 -0
- zenml/service_connectors/service_connector_utils.py +408 -0
- zenml/stack/stack.py +3 -6
- zenml/stack_deployments/__init__.py +14 -0
- zenml/stack_deployments/aws_stack_deployment.py +254 -0
- zenml/stack_deployments/azure_stack_deployment.py +179 -0
- zenml/stack_deployments/gcp_stack_deployment.py +269 -0
- zenml/stack_deployments/stack_deployment.py +218 -0
- zenml/stack_deployments/utils.py +48 -0
- zenml/steps/base_step.py +7 -5
- zenml/utils/function_utils.py +2 -2
- zenml/utils/pagination_utils.py +7 -5
- zenml/utils/pipeline_docker_image_builder.py +105 -68
- zenml/utils/pydantic_utils.py +6 -5
- zenml/utils/source_utils.py +4 -1
- zenml/zen_server/cloud_utils.py +18 -3
- zenml/zen_server/dashboard/assets/{404-CDPQCl4D.js → 404-B_YdvmwS.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-l_1hUr1S.js} +2 -2
- zenml/zen_server/dashboard/assets/@tanstack-DYiOyJUL.js +22 -0
- zenml/zen_server/dashboard/assets/AwarenessChannel-CFg5iX4Z.js +1 -0
- zenml/zen_server/dashboard/assets/{CodeSnippet-BidtnWOi.js → CodeSnippet-Dvkx_82E.js} +2 -2
- zenml/zen_server/dashboard/assets/CollapsibleCard-opiuBHHc.js +1 -0
- zenml/zen_server/dashboard/assets/Commands-DoN1xrEq.js +1 -0
- zenml/zen_server/dashboard/assets/CopyButton-Cr7xYEPb.js +2 -0
- zenml/zen_server/dashboard/assets/{CsvVizualization-BOuez-fG.js → CsvVizualization-Ck-nZ43m.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-kLtljEOM.js +1 -0
- zenml/zen_server/dashboard/assets/ExecutionStatus-DguLLgTK.js +1 -0
- zenml/zen_server/dashboard/assets/Helpbox-BXUMP21n.js +1 -0
- zenml/zen_server/dashboard/assets/Infobox-DSt0O-dm.js +1 -0
- zenml/zen_server/dashboard/assets/InlineAvatar-xsrsIGE-.js +1 -0
- zenml/zen_server/dashboard/assets/{MarkdownVisualization-DsB2QZiK.js → MarkdownVisualization-xp3hhULl.js} +2 -2
- zenml/zen_server/dashboard/assets/Pagination-C6X-mifw.js +1 -0
- zenml/zen_server/dashboard/assets/PasswordChecker-DUveqlva.js +1 -0
- zenml/zen_server/dashboard/assets/SetPassword-BXGTWiwj.js +1 -0
- zenml/zen_server/dashboard/assets/SuccessStep-DZC60t0x.js +1 -0
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DnM-c11H.js → UpdatePasswordSchemas-DGvwFWO1.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-right-double-CJ50E9Gr.js → chevron-right-double-CZBOf6JM.js} +1 -1
- zenml/zen_server/dashboard/assets/cloud-only-C_yFCAkP.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-BczVOqUf.js +55 -0
- zenml/zen_server/dashboard/assets/index-EpMIKgrI.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-CrHrndTI.js} +1 -1
- zenml/zen_server/dashboard/assets/logs-D8k8BVFf.js +1 -0
- zenml/zen_server/dashboard/assets/not-found-DYa4pC-C.js +1 -0
- zenml/zen_server/dashboard/assets/package-B3fWP-Dh.js +1 -0
- zenml/zen_server/dashboard/assets/page-1h_sD1jz.js +1 -0
- zenml/zen_server/dashboard/assets/{page-yN4rZ-ZS.js → page-1iL8aMqs.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Bi5AI0S7.js → page-2grKx_MY.js} +1 -1
- zenml/zen_server/dashboard/assets/page-5NCOHOsy.js +1 -0
- zenml/zen_server/dashboard/assets/page-8a4UMKXZ.js +1 -0
- zenml/zen_server/dashboard/assets/{page-AQKopn_4.js → page-B6h3iaHJ.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BDns21Iz.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BmkSiYeQ.js → page-BhgCDInH.js} +2 -2
- zenml/zen_server/dashboard/assets/{page-BzVZGExK.js → page-Bi-wtWiO.js} +2 -2
- zenml/zen_server/dashboard/assets/page-BkeAAYwp.js +1 -0
- zenml/zen_server/dashboard/assets/page-BkuQDIf-.js +1 -0
- zenml/zen_server/dashboard/assets/page-BnaevhnB.js +1 -0
- zenml/zen_server/dashboard/assets/page-Bq0YxkLV.js +1 -0
- zenml/zen_server/dashboard/assets/page-Bs2F4eoD.js +2 -0
- zenml/zen_server/dashboard/assets/page-C6-UGEbH.js +1 -0
- zenml/zen_server/dashboard/assets/page-CCNRIt_f.js +1 -0
- zenml/zen_server/dashboard/assets/page-CHNxpz3n.js +1 -0
- zenml/zen_server/dashboard/assets/page-DgorQFqi.js +1 -0
- zenml/zen_server/dashboard/assets/page-K8ebxVIs.js +1 -0
- zenml/zen_server/dashboard/assets/{page-CuT1SUik.js → page-MFQyIJd3.js} +1 -1
- zenml/zen_server/dashboard/assets/page-TgCF0P_U.js +1 -0
- zenml/zen_server/dashboard/assets/page-ZnCEe-eK.js +9 -0
- zenml/zen_server/dashboard/assets/{page-BW6Ket3a.js → page-uA5prJGY.js} +1 -1
- zenml/zen_server/dashboard/assets/persist-D7HJNBWx.js +1 -0
- zenml/zen_server/dashboard/assets/{play-circle-DK5QMJyp.js → play-circle-CNtZKDnW.js} +1 -1
- zenml/zen_server/dashboard/assets/plus-C8WOyCzt.js +1 -0
- zenml/zen_server/dashboard/assets/stack-detail-query-Cficsl6d.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-7d8xi1tS.js +1 -0
- zenml/zen_server/dashboard/assets/{url-6_xv0WJS.js → url-D7mAQGUM.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.12246c7548e71e2c4438e496360de80c.js} +4 -4
- zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
- zenml/zen_server/dashboard_legacy/static/js/main.3b27024b.chunk.js +2 -0
- zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js.map → main.3b27024b.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/utils.py +10 -2
- zenml/zen_server/rbac/zenml_cloud_rbac.py +11 -5
- zenml/zen_server/routers/devices_endpoints.py +4 -1
- zenml/zen_server/routers/server_endpoints.py +29 -2
- zenml/zen_server/routers/service_connectors_endpoints.py +57 -0
- zenml/zen_server/routers/stack_deployment_endpoints.py +158 -0
- zenml/zen_server/routers/steps_endpoints.py +2 -1
- zenml/zen_server/routers/workspaces_endpoints.py +64 -0
- zenml/zen_server/zen_server_api.py +2 -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/0.62.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
- zenml/zen_stores/migrations/versions/b4fca5241eea_migrate_onboarding_state.py +167 -0
- zenml/zen_stores/rest_zen_store.py +149 -4
- zenml/zen_stores/schemas/component_schemas.py +14 -0
- zenml/zen_stores/schemas/server_settings_schemas.py +23 -11
- zenml/zen_stores/schemas/stack_schemas.py +10 -0
- zenml/zen_stores/schemas/step_run_schemas.py +27 -11
- zenml/zen_stores/sql_zen_store.py +450 -6
- zenml/zen_stores/zen_store_interface.py +80 -0
- {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/METADATA +35 -13
- {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/RECORD +227 -191
- 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/chevron-down-zcvCWmyP.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/zen_server/dashboard/assets/update-server-settings-mutation-0Wgz8pUE.js +0 -1
- zenml/zen_server/dashboard_legacy/static/js/main.ac2f17d0.chunk.js +0 -2
- {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.62.0.dev20240726.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.62.0
|
24
|
+
helm install my-zenml oci://public.ecr.aws/zenml/zenml --version 0.62.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/utils.py
CHANGED
@@ -103,7 +103,9 @@ def dehydrate_response_model(
|
|
103
103
|
)
|
104
104
|
|
105
105
|
dehydrated_values = {}
|
106
|
-
for
|
106
|
+
# See `get_subresources_for_model(...)` for a detailed explanation why we
|
107
|
+
# need to use `model.__iter__()` here
|
108
|
+
for key, value in model.__iter__():
|
107
109
|
dehydrated_values[key] = _dehydrate_value(
|
108
110
|
value, permissions=permissions
|
109
111
|
)
|
@@ -484,7 +486,13 @@ def get_subresources_for_model(
|
|
484
486
|
"""
|
485
487
|
resources = set()
|
486
488
|
|
487
|
-
|
489
|
+
# We don't want to use `model.model_dump()` here as that recursively
|
490
|
+
# converts models to dicts, but we want to preserve those classes for
|
491
|
+
# the recursive `_get_subresources_for_value` calls.
|
492
|
+
# We previously used `dict(model)` here, but that lead to issues with
|
493
|
+
# models overwriting `__getattr__`, this `model.__iter__()` has the same
|
494
|
+
# results though.
|
495
|
+
for _, value in model.__iter__():
|
488
496
|
resources.update(_get_subresources_for_value(value))
|
489
497
|
|
490
498
|
return resources
|
@@ -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)
|
@@ -27,7 +27,7 @@ from zenml.constants import (
|
|
27
27
|
DEVICES,
|
28
28
|
VERSION_1,
|
29
29
|
)
|
30
|
-
from zenml.enums import OAuthDeviceStatus
|
30
|
+
from zenml.enums import OAuthDeviceStatus, OnboardingStep
|
31
31
|
from zenml.models import (
|
32
32
|
OAuthDeviceFilter,
|
33
33
|
OAuthDeviceInternalUpdate,
|
@@ -270,6 +270,9 @@ def verify_authorized_device(
|
|
270
270
|
update=update,
|
271
271
|
)
|
272
272
|
|
273
|
+
store.update_onboarding_state(
|
274
|
+
completed_steps={OnboardingStep.DEVICE_VERIFIED}
|
275
|
+
)
|
273
276
|
return device_model
|
274
277
|
|
275
278
|
|
@@ -13,12 +13,19 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for authentication (login)."""
|
15
15
|
|
16
|
-
from typing import Optional
|
16
|
+
from typing import List, Optional
|
17
17
|
|
18
18
|
from fastapi import APIRouter, Security
|
19
19
|
|
20
20
|
import zenml
|
21
|
-
from zenml.constants import
|
21
|
+
from zenml.constants import (
|
22
|
+
ACTIVATE,
|
23
|
+
API,
|
24
|
+
INFO,
|
25
|
+
ONBOARDING_STATE,
|
26
|
+
SERVER_SETTINGS,
|
27
|
+
VERSION_1,
|
28
|
+
)
|
22
29
|
from zenml.enums import AuthScheme
|
23
30
|
from zenml.exceptions import IllegalOperationError
|
24
31
|
from zenml.models import (
|
@@ -64,6 +71,26 @@ def server_info() -> ServerModel:
|
|
64
71
|
return zen_store().get_store_info()
|
65
72
|
|
66
73
|
|
74
|
+
@router.get(
|
75
|
+
ONBOARDING_STATE,
|
76
|
+
responses={
|
77
|
+
401: error_response,
|
78
|
+
404: error_response,
|
79
|
+
422: error_response,
|
80
|
+
},
|
81
|
+
)
|
82
|
+
@handle_exceptions
|
83
|
+
def get_onboarding_state(
|
84
|
+
_: AuthContext = Security(authorize),
|
85
|
+
) -> List[str]:
|
86
|
+
"""Get the onboarding state of the server.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
The onboarding state of the server.
|
90
|
+
"""
|
91
|
+
return zen_store().get_onboarding_state()
|
92
|
+
|
93
|
+
|
67
94
|
# We don't have any concrete value that tells us whether a server is a cloud
|
68
95
|
# tenant, so we use `external_server_id` as the best proxy option.
|
69
96
|
# For cloud tenants, we don't add these endpoints as the server settings don't
|
@@ -21,6 +21,7 @@ from fastapi import APIRouter, Depends, Security
|
|
21
21
|
from zenml.constants import (
|
22
22
|
API,
|
23
23
|
SERVICE_CONNECTOR_CLIENT,
|
24
|
+
SERVICE_CONNECTOR_FULL_STACK,
|
24
25
|
SERVICE_CONNECTOR_TYPES,
|
25
26
|
SERVICE_CONNECTOR_VERIFY,
|
26
27
|
SERVICE_CONNECTORS,
|
@@ -35,6 +36,13 @@ from zenml.models import (
|
|
35
36
|
ServiceConnectorTypeModel,
|
36
37
|
ServiceConnectorUpdate,
|
37
38
|
)
|
39
|
+
from zenml.models.v2.misc.full_stack import (
|
40
|
+
ServiceConnectorInfo,
|
41
|
+
ServiceConnectorResourcesInfo,
|
42
|
+
)
|
43
|
+
from zenml.service_connectors.service_connector_utils import (
|
44
|
+
get_resources_options_from_resource_model_for_full_stack,
|
45
|
+
)
|
38
46
|
from zenml.zen_server.auth import AuthContext, authorize
|
39
47
|
from zenml.zen_server.exceptions import error_response
|
40
48
|
from zenml.zen_server.rbac.endpoint_utils import (
|
@@ -393,3 +401,52 @@ def get_service_connector_type(
|
|
393
401
|
The requested service connector type.
|
394
402
|
"""
|
395
403
|
return zen_store().get_service_connector_type(connector_type)
|
404
|
+
|
405
|
+
|
406
|
+
@router.post(
|
407
|
+
SERVICE_CONNECTOR_FULL_STACK,
|
408
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
409
|
+
)
|
410
|
+
@handle_exceptions
|
411
|
+
def get_resources_based_on_service_connector_info(
|
412
|
+
connector_info: Optional[ServiceConnectorInfo] = None,
|
413
|
+
connector_uuid: Optional[UUID] = None,
|
414
|
+
_: AuthContext = Security(authorize),
|
415
|
+
) -> ServiceConnectorResourcesInfo:
|
416
|
+
"""Gets the list of resources that a service connector can access.
|
417
|
+
|
418
|
+
Args:
|
419
|
+
connector_info: The service connector info.
|
420
|
+
connector_uuid: The service connector uuid.
|
421
|
+
|
422
|
+
Returns:
|
423
|
+
The list of resources that the service connector configuration has
|
424
|
+
access to and consumable from UI/CLI.
|
425
|
+
|
426
|
+
Raises:
|
427
|
+
ValueError: If both connector_info and connector_uuid are provided.
|
428
|
+
ValueError: If neither connector_info nor connector_uuid are provided.
|
429
|
+
"""
|
430
|
+
if connector_info is not None and connector_uuid is not None:
|
431
|
+
raise ValueError(
|
432
|
+
"Only one of connector_info or connector_uuid must be provided."
|
433
|
+
)
|
434
|
+
if connector_info is None and connector_uuid is None:
|
435
|
+
raise ValueError(
|
436
|
+
"Either connector_info or connector_uuid must be provided."
|
437
|
+
)
|
438
|
+
|
439
|
+
if connector_info is not None:
|
440
|
+
verify_permission(
|
441
|
+
resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
|
442
|
+
)
|
443
|
+
elif connector_uuid is not None:
|
444
|
+
verify_permission(
|
445
|
+
resource_type=ResourceType.SERVICE_CONNECTOR,
|
446
|
+
action=Action.READ,
|
447
|
+
resource_id=connector_uuid,
|
448
|
+
)
|
449
|
+
|
450
|
+
return get_resources_options_from_resource_model_for_full_stack(
|
451
|
+
connector_details=connector_info or connector_uuid # type: ignore[arg-type]
|
452
|
+
)
|
@@ -0,0 +1,158 @@
|
|
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 stack deployments."""
|
15
|
+
|
16
|
+
import datetime
|
17
|
+
from typing import Optional
|
18
|
+
|
19
|
+
from fastapi import APIRouter, Request, Security
|
20
|
+
|
21
|
+
from zenml.constants import (
|
22
|
+
API,
|
23
|
+
CONFIG,
|
24
|
+
INFO,
|
25
|
+
STACK,
|
26
|
+
STACK_DEPLOYMENT,
|
27
|
+
STACK_DEPLOYMENT_API_TOKEN_EXPIRATION,
|
28
|
+
VERSION_1,
|
29
|
+
)
|
30
|
+
from zenml.enums import StackDeploymentProvider
|
31
|
+
from zenml.models import (
|
32
|
+
DeployedStack,
|
33
|
+
StackDeploymentConfig,
|
34
|
+
StackDeploymentInfo,
|
35
|
+
)
|
36
|
+
from zenml.stack_deployments.utils import get_stack_deployment_class
|
37
|
+
from zenml.zen_server.auth import AuthContext, authorize
|
38
|
+
from zenml.zen_server.exceptions import error_response
|
39
|
+
from zenml.zen_server.rbac.models import Action, ResourceType
|
40
|
+
from zenml.zen_server.rbac.utils import verify_permission
|
41
|
+
from zenml.zen_server.utils import (
|
42
|
+
handle_exceptions,
|
43
|
+
)
|
44
|
+
|
45
|
+
router = APIRouter(
|
46
|
+
prefix=API + VERSION_1 + STACK_DEPLOYMENT,
|
47
|
+
tags=["stacks"],
|
48
|
+
responses={401: error_response, 403: error_response},
|
49
|
+
)
|
50
|
+
|
51
|
+
|
52
|
+
@router.get(
|
53
|
+
INFO,
|
54
|
+
)
|
55
|
+
@handle_exceptions
|
56
|
+
def get_stack_deployment_info(
|
57
|
+
provider: StackDeploymentProvider,
|
58
|
+
_: AuthContext = Security(authorize),
|
59
|
+
) -> StackDeploymentInfo:
|
60
|
+
"""Get information about a stack deployment provider.
|
61
|
+
|
62
|
+
Args:
|
63
|
+
provider: The stack deployment provider.
|
64
|
+
|
65
|
+
Returns:
|
66
|
+
Information about the stack deployment provider.
|
67
|
+
"""
|
68
|
+
stack_deployment_class = get_stack_deployment_class(provider)
|
69
|
+
return stack_deployment_class.get_deployment_info()
|
70
|
+
|
71
|
+
|
72
|
+
@router.get(
|
73
|
+
CONFIG,
|
74
|
+
)
|
75
|
+
@handle_exceptions
|
76
|
+
def get_stack_deployment_config(
|
77
|
+
request: Request,
|
78
|
+
provider: StackDeploymentProvider,
|
79
|
+
stack_name: str,
|
80
|
+
location: Optional[str] = None,
|
81
|
+
auth_context: AuthContext = Security(authorize),
|
82
|
+
) -> StackDeploymentConfig:
|
83
|
+
"""Return the URL to deploy the ZenML stack to the specified cloud provider.
|
84
|
+
|
85
|
+
Args:
|
86
|
+
request: The FastAPI request object.
|
87
|
+
provider: The stack deployment provider.
|
88
|
+
stack_name: The name of the stack.
|
89
|
+
location: The location where the stack should be deployed.
|
90
|
+
auth_context: The authentication context.
|
91
|
+
|
92
|
+
Returns:
|
93
|
+
The cloud provider console URL where the stack will be deployed and
|
94
|
+
the configuration for the stack deployment.
|
95
|
+
"""
|
96
|
+
verify_permission(
|
97
|
+
resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
|
98
|
+
)
|
99
|
+
verify_permission(
|
100
|
+
resource_type=ResourceType.STACK_COMPONENT,
|
101
|
+
action=Action.CREATE,
|
102
|
+
)
|
103
|
+
verify_permission(resource_type=ResourceType.STACK, action=Action.CREATE)
|
104
|
+
|
105
|
+
stack_deployment_class = get_stack_deployment_class(provider)
|
106
|
+
# Get the base server URL used to call this FastAPI endpoint
|
107
|
+
url = request.url.replace(path="").replace(query="")
|
108
|
+
# Use HTTPS for the URL
|
109
|
+
url = url.replace(scheme="https")
|
110
|
+
|
111
|
+
token = auth_context.access_token
|
112
|
+
assert token is not None
|
113
|
+
|
114
|
+
# A new API token is generated for the stack deployment
|
115
|
+
expires = datetime.datetime.utcnow() + datetime.timedelta(
|
116
|
+
minutes=STACK_DEPLOYMENT_API_TOKEN_EXPIRATION
|
117
|
+
)
|
118
|
+
api_token = token.encode(expires=expires)
|
119
|
+
|
120
|
+
return stack_deployment_class(
|
121
|
+
stack_name=stack_name,
|
122
|
+
location=location,
|
123
|
+
zenml_server_url=str(url),
|
124
|
+
zenml_server_api_token=api_token,
|
125
|
+
).get_deployment_config()
|
126
|
+
|
127
|
+
|
128
|
+
@router.get(
|
129
|
+
STACK,
|
130
|
+
)
|
131
|
+
@handle_exceptions
|
132
|
+
def get_deployed_stack(
|
133
|
+
provider: StackDeploymentProvider,
|
134
|
+
stack_name: str,
|
135
|
+
location: Optional[str] = None,
|
136
|
+
date_start: Optional[datetime.datetime] = None,
|
137
|
+
_: AuthContext = Security(authorize),
|
138
|
+
) -> Optional[DeployedStack]:
|
139
|
+
"""Return a matching ZenML stack that was deployed and registered.
|
140
|
+
|
141
|
+
Args:
|
142
|
+
provider: The stack deployment provider.
|
143
|
+
stack_name: The name of the stack.
|
144
|
+
location: The location where the stack should be deployed.
|
145
|
+
date_start: The date when the deployment started.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
The ZenML stack that was deployed and registered or None if the stack
|
149
|
+
was not found.
|
150
|
+
"""
|
151
|
+
stack_deployment_class = get_stack_deployment_class(provider)
|
152
|
+
return stack_deployment_class(
|
153
|
+
stack_name=stack_name,
|
154
|
+
location=location,
|
155
|
+
# These fields are not needed for this operation
|
156
|
+
zenml_server_url="",
|
157
|
+
zenml_server_api_token="",
|
158
|
+
).get_stack(date_start=date_start)
|
@@ -117,7 +117,8 @@ def create_run_step(
|
|
117
117
|
pipeline_run = zen_store().get_run(step.pipeline_run_id)
|
118
118
|
verify_permission_for_model(pipeline_run, action=Action.UPDATE)
|
119
119
|
|
120
|
-
|
120
|
+
step_response = zen_store().create_run_step(step_run=step)
|
121
|
+
return dehydrate_response_model(step_response)
|
121
122
|
|
122
123
|
|
123
124
|
@router.get(
|
@@ -22,6 +22,7 @@ from zenml.constants import (
|
|
22
22
|
API,
|
23
23
|
ARTIFACTS,
|
24
24
|
CODE_REPOSITORIES,
|
25
|
+
FULL_STACK,
|
25
26
|
GET_OR_CREATE,
|
26
27
|
MODEL_VERSIONS,
|
27
28
|
MODELS,
|
@@ -51,6 +52,7 @@ from zenml.models import (
|
|
51
52
|
ComponentFilter,
|
52
53
|
ComponentRequest,
|
53
54
|
ComponentResponse,
|
55
|
+
FullStackRequest,
|
54
56
|
ModelRequest,
|
55
57
|
ModelResponse,
|
56
58
|
ModelVersionArtifactRequest,
|
@@ -349,6 +351,68 @@ def create_stack(
|
|
349
351
|
)
|
350
352
|
|
351
353
|
|
354
|
+
@router.post(
|
355
|
+
WORKSPACES + "/{workspace_name_or_id}" + FULL_STACK,
|
356
|
+
response_model=StackResponse,
|
357
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
358
|
+
)
|
359
|
+
@handle_exceptions
|
360
|
+
def create_full_stack(
|
361
|
+
workspace_name_or_id: Union[str, UUID],
|
362
|
+
full_stack: FullStackRequest,
|
363
|
+
auth_context: AuthContext = Security(authorize),
|
364
|
+
) -> StackResponse:
|
365
|
+
"""Creates a stack for a particular workspace.
|
366
|
+
|
367
|
+
Args:
|
368
|
+
workspace_name_or_id: Name or ID of the workspace.
|
369
|
+
full_stack: Stack to register.
|
370
|
+
auth_context: Authentication context.
|
371
|
+
|
372
|
+
Returns:
|
373
|
+
The created stack.
|
374
|
+
"""
|
375
|
+
workspace = zen_store().get_workspace(workspace_name_or_id)
|
376
|
+
|
377
|
+
is_connector_create_needed = False
|
378
|
+
for connector_id_or_info in full_stack.service_connectors:
|
379
|
+
if isinstance(connector_id_or_info, UUID):
|
380
|
+
service_connector = zen_store().get_service_connector(
|
381
|
+
connector_id_or_info, hydrate=False
|
382
|
+
)
|
383
|
+
verify_permission_for_model(
|
384
|
+
model=service_connector, action=Action.READ
|
385
|
+
)
|
386
|
+
else:
|
387
|
+
is_connector_create_needed = True
|
388
|
+
if is_connector_create_needed:
|
389
|
+
verify_permission(
|
390
|
+
resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
|
391
|
+
)
|
392
|
+
|
393
|
+
is_component_create_needed = False
|
394
|
+
for component_id_or_info in full_stack.components.values():
|
395
|
+
if isinstance(component_id_or_info, UUID):
|
396
|
+
component = zen_store().get_stack_component(
|
397
|
+
component_id_or_info, hydrate=False
|
398
|
+
)
|
399
|
+
verify_permission_for_model(model=component, action=Action.READ)
|
400
|
+
else:
|
401
|
+
is_component_create_needed = True
|
402
|
+
if is_component_create_needed:
|
403
|
+
verify_permission(
|
404
|
+
resource_type=ResourceType.STACK_COMPONENT,
|
405
|
+
action=Action.CREATE,
|
406
|
+
)
|
407
|
+
|
408
|
+
verify_permission(resource_type=ResourceType.STACK, action=Action.CREATE)
|
409
|
+
|
410
|
+
full_stack.user = auth_context.user.id
|
411
|
+
full_stack.workspace = workspace.id
|
412
|
+
|
413
|
+
return zen_store().create_full_stack(full_stack)
|
414
|
+
|
415
|
+
|
352
416
|
@router.get(
|
353
417
|
WORKSPACES + "/{workspace_name_or_id}" + STACK_COMPONENTS,
|
354
418
|
response_model=Page[ComponentResponse],
|