zenml-nightly 0.62.0.dev20240729__py3-none-any.whl → 0.64.0.dev20240809__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 +2 -2
- RELEASE_NOTES.md +120 -0
- zenml/VERSION +1 -1
- zenml/__init__.py +0 -4
- zenml/actions/pipeline_run/pipeline_run_action.py +19 -17
- zenml/analytics/enums.py +4 -6
- zenml/cli/__init__.py +28 -76
- zenml/cli/base.py +2 -2
- zenml/cli/pipeline.py +54 -61
- zenml/cli/stack.py +6 -8
- zenml/cli/web_login.py +8 -0
- zenml/client.py +232 -103
- zenml/config/build_configuration.py +43 -17
- zenml/config/compiler.py +14 -22
- zenml/config/docker_settings.py +80 -57
- zenml/config/pipeline_run_configuration.py +3 -0
- zenml/config/server_config.py +3 -0
- zenml/config/source.py +60 -1
- zenml/constants.py +11 -2
- zenml/entrypoints/base_entrypoint_configuration.py +53 -8
- zenml/enums.py +4 -1
- zenml/environment.py +25 -9
- zenml/image_builders/base_image_builder.py +1 -1
- zenml/image_builders/build_context.py +25 -72
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +13 -4
- zenml/integrations/azure/__init__.py +4 -0
- zenml/integrations/azure/flavors/__init__.py +11 -0
- zenml/integrations/azure/flavors/azureml_orchestrator_flavor.py +263 -0
- zenml/{_hub → integrations/azure/orchestrators}/__init__.py +7 -2
- zenml/integrations/azure/orchestrators/azureml_orchestrator.py +544 -0
- zenml/integrations/azure/orchestrators/azureml_orchestrator_entrypoint_config.py +86 -0
- zenml/integrations/azure/step_operators/azureml_step_operator.py +3 -0
- zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +20 -2
- zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +19 -13
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +7 -2
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +123 -6
- zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +1 -1
- zenml/integrations/mlflow/__init__.py +1 -1
- zenml/integrations/mlflow/experiment_trackers/mlflow_experiment_tracker.py +3 -1
- zenml/integrations/mlflow/flavors/mlflow_experiment_tracker_flavor.py +3 -0
- zenml/logger.py +13 -0
- zenml/models/__init__.py +26 -22
- zenml/models/v2/base/filter.py +32 -0
- zenml/models/v2/core/pipeline.py +73 -89
- zenml/models/v2/core/pipeline_build.py +15 -11
- zenml/models/v2/core/pipeline_deployment.py +72 -24
- zenml/models/v2/core/pipeline_run.py +65 -1
- zenml/models/v2/core/run_template.py +393 -0
- zenml/models/v2/core/server_settings.py +12 -0
- zenml/models/v2/core/user.py +0 -21
- zenml/models/v2/misc/server_models.py +7 -1
- zenml/models/v2/misc/stack_deployment.py +5 -0
- zenml/models/v2/misc/user_auth.py +0 -7
- zenml/new/pipelines/build_utils.py +220 -89
- zenml/new/pipelines/code_archive.py +157 -0
- zenml/new/pipelines/pipeline.py +46 -78
- zenml/new/pipelines/run_utils.py +79 -1
- zenml/post_execution/pipeline.py +1 -4
- zenml/service_connectors/service_connector_utils.py +18 -2
- zenml/stack_deployments/aws_stack_deployment.py +32 -8
- zenml/stack_deployments/azure_stack_deployment.py +122 -10
- zenml/stack_deployments/gcp_stack_deployment.py +36 -7
- zenml/stack_deployments/stack_deployment.py +23 -7
- zenml/steps/base_step.py +3 -0
- zenml/steps/utils.py +0 -4
- zenml/utils/archivable.py +149 -0
- zenml/utils/code_utils.py +244 -0
- zenml/utils/notebook_utils.py +122 -0
- zenml/utils/package_utils.py +39 -0
- zenml/utils/pipeline_docker_image_builder.py +3 -96
- zenml/utils/source_utils.py +109 -1
- zenml/zen_server/dashboard/assets/{404-B_YdvmwS.js → 404-CRAA_Lew.js} +1 -1
- zenml/zen_server/dashboard/assets/@radix-BXWm7HOa.js +85 -0
- zenml/zen_server/dashboard/assets/{@react-router-CO-OsFwI.js → @react-router-l3lMcXA2.js} +1 -1
- zenml/zen_server/dashboard/assets/{@reactflow-l_1hUr1S.js → @reactflow-CeVxyqYT.js} +2 -2
- zenml/zen_server/dashboard/assets/{@tanstack-DYiOyJUL.js → @tanstack-FmcYZMuX.js} +4 -4
- zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-ErO9aOgK.js +1 -0
- zenml/zen_server/dashboard/assets/{AwarenessChannel-CFg5iX4Z.js → AwarenessChannel-CLXo5rKM.js} +1 -1
- zenml/zen_server/dashboard/assets/{CodeSnippet-Dvkx_82E.js → CodeSnippet-D0VLxT2A.js} +2 -2
- zenml/zen_server/dashboard/assets/CollapsibleCard-BaUPiVg0.js +1 -0
- zenml/zen_server/dashboard/assets/{Commands-DoN1xrEq.js → Commands-JrcZK-3j.js} +1 -1
- zenml/zen_server/dashboard/assets/CopyButton-Dbo52T1K.js +2 -0
- zenml/zen_server/dashboard/assets/{CsvVizualization-Ck-nZ43m.js → CsvVizualization-D3kAypDj.js} +3 -3
- zenml/zen_server/dashboard/assets/DisplayDate-DizbSeT-.js +1 -0
- zenml/zen_server/dashboard/assets/EditSecretDialog-Bd7mFLS4.js +1 -0
- zenml/zen_server/dashboard/assets/{EmptyState-BMLnFVlB.js → EmptyState-BHblM39I.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-kLtljEOM.js → Error-C6LeJSER.js} +1 -1
- zenml/zen_server/dashboard/assets/{ExecutionStatus-DguLLgTK.js → ExecutionStatus-jH4OrWBq.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-BXUMP21n.js → Helpbox-aAB2XP-z.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-DSt0O-dm.js → Infobox-BQ0aty32.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-xsrsIGE-.js → InlineAvatar-DpTLgM3Q.js} +1 -1
- zenml/zen_server/dashboard/assets/Lock-CNyJvf2r.js +1 -0
- zenml/zen_server/dashboard/assets/{MarkdownVisualization-xp3hhULl.js → MarkdownVisualization-Bajxn0HY.js} +1 -1
- zenml/zen_server/dashboard/assets/NumberBox-BmKE0qnO.js +1 -0
- zenml/zen_server/dashboard/assets/{PasswordChecker-DUveqlva.js → PasswordChecker-yGGoJSB-.js} +1 -1
- zenml/zen_server/dashboard/assets/ProviderRadio-BBqkIuTd.js +1 -0
- zenml/zen_server/dashboard/assets/RadioItem-xLhXoiFV.js +1 -0
- zenml/zen_server/dashboard/assets/SearchField-C9R0mdaX.js +1 -0
- zenml/zen_server/dashboard/assets/{SetPassword-BXGTWiwj.js → SetPassword-52sNxNiO.js} +1 -1
- zenml/zen_server/dashboard/assets/{SuccessStep-DZC60t0x.js → SuccessStep-DlkItqYG.js} +1 -1
- zenml/zen_server/dashboard/assets/Tick-uxv80Q6a.js +1 -0
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DGvwFWO1.js → UpdatePasswordSchemas-oN4G3sKz.js} +1 -1
- zenml/zen_server/dashboard/assets/{aws-BgKTfTfx.js → aws-0_3UsPif.js} +1 -1
- zenml/zen_server/dashboard/assets/{check-circle-i56092KI.js → check-circle-1_I207rW.js} +1 -1
- zenml/zen_server/dashboard/assets/chevron-down-BpaF8JqM.js +1 -0
- zenml/zen_server/dashboard/assets/{chevron-right-double-CZBOf6JM.js → chevron-right-double-Dk8e2L99.js} +1 -1
- zenml/zen_server/dashboard/assets/{cloud-only-C_yFCAkP.js → cloud-only-BkUuI0lZ.js} +1 -1
- zenml/zen_server/dashboard/assets/components-Br2ezRib.js +1 -0
- zenml/zen_server/dashboard/assets/{copy-BXNk6BjL.js → copy-f3XGPPxt.js} +1 -1
- zenml/zen_server/dashboard/assets/{database-1xWSgZfO.js → database-cXYNX9tt.js} +1 -1
- zenml/zen_server/dashboard/assets/{docker-CQMVm_4d.js → docker-8uj__HHK.js} +1 -1
- zenml/zen_server/dashboard/assets/dots-horizontal-sKQlWEni.js +1 -0
- zenml/zen_server/dashboard/assets/edit-C0MVvPD2.js +1 -0
- zenml/zen_server/dashboard/assets/{file-text-CqD_iu6l.js → file-text-B9JibxTs.js} +1 -1
- zenml/zen_server/dashboard/assets/{help-bu_DgLKI.js → help-FuHlZwn0.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-rK_Wuy2W.js → index-Bd1xgUQG.js} +1 -1
- zenml/zen_server/dashboard/assets/index-DaGknux4.css +1 -0
- zenml/zen_server/dashboard/assets/{index-BczVOqUf.js → index-DhIZtpxB.js} +5 -5
- zenml/zen_server/dashboard/assets/index.esm-DT4uyn2i.js +1 -0
- zenml/zen_server/dashboard/assets/layout-D6oiSbfd.js +1 -0
- zenml/zen_server/dashboard/assets/{login-mutation-CrHrndTI.js → login-mutation-13A_JSVA.js} +1 -1
- zenml/zen_server/dashboard/assets/{logs-D8k8BVFf.js → logs-CgeE2vZP.js} +1 -1
- zenml/zen_server/dashboard/assets/{not-found-DYa4pC-C.js → not-found-B0Mmb90p.js} +1 -1
- zenml/zen_server/dashboard/assets/package-DdkziX79.js +1 -0
- zenml/zen_server/dashboard/assets/page-7-v2OBm-.js +1 -0
- zenml/zen_server/dashboard/assets/{page-MFQyIJd3.js → page-B3ozwdD1.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BkuQDIf-.js → page-BGwA9B1M.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-1iL8aMqs.js → page-BkjAUyTA.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BnacgBiy.js +1 -0
- zenml/zen_server/dashboard/assets/page-BxF_KMQ3.js +2 -0
- zenml/zen_server/dashboard/assets/page-C4POHC0K.js +1 -0
- zenml/zen_server/dashboard/assets/page-C9kudd44.js +9 -0
- zenml/zen_server/dashboard/assets/page-CA1j3GpJ.js +1 -0
- zenml/zen_server/dashboard/assets/page-CCY6yfmu.js +1 -0
- zenml/zen_server/dashboard/assets/page-CgTe7Bme.js +1 -0
- zenml/zen_server/dashboard/assets/{page-8a4UMKXZ.js → page-Cgn-6v2Y.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CxQmQqDw.js +1 -0
- zenml/zen_server/dashboard/assets/page-D2Goey3H.js +1 -0
- zenml/zen_server/dashboard/assets/page-DLpOnf7u.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BhgCDInH.js → page-DSTQnBk-.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-1h_sD1jz.js → page-DTysUGOy.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-2grKx_MY.js → page-D_EXUFJb.js} +1 -1
- zenml/zen_server/dashboard/assets/page-Db15QzsM.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BDns21Iz.js → page-DugsjcQ_.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-C6-UGEbH.js → page-OFKSPyN7.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BkeAAYwp.js → page-RnG-qhv9.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CCNRIt_f.js → page-T2BtjwPl.js} +1 -1
- zenml/zen_server/dashboard/assets/page-TXe1Eo3Z.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BnaevhnB.js → page-YiF_fNbe.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-uA5prJGY.js → page-hQaiQXfg.js} +1 -1
- zenml/zen_server/dashboard/assets/persist-3-5nOJ6m.js +1 -0
- zenml/zen_server/dashboard/assets/{play-circle-CNtZKDnW.js → play-circle-XSkLR12B.js} +1 -1
- zenml/zen_server/dashboard/assets/plus-FB9-lEq_.js +1 -0
- zenml/zen_server/dashboard/assets/refresh-COb6KYDi.js +1 -0
- zenml/zen_server/dashboard/assets/sharedSchema-BoYx_B_L.js +14 -0
- zenml/zen_server/dashboard/assets/{stack-detail-query-Cficsl6d.js → stack-detail-query-B-US_-wa.js} +1 -1
- zenml/zen_server/dashboard/assets/{terminal-By9cErXc.js → terminal-grtjrIEJ.js} +1 -1
- zenml/zen_server/dashboard/assets/trash-Cd5CSFqA.js +1 -0
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-7d8xi1tS.js → update-server-settings-mutation-B8GB_ubU.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-D7mAQGUM.js → url-hcMJkz8p.js} +1 -1
- zenml/zen_server/dashboard/assets/{zod-BhoGpZ63.js → zod-CnykDKJj.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.12246c7548e71e2c4438e496360de80c.js → precache-manifest.9c473c96a43298343a7ce1256183123b.js} +4 -4
- zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
- zenml/zen_server/dashboard_legacy/static/js/{main.3b27024b.chunk.js → main.463c90b9.chunk.js} +2 -2
- zenml/zen_server/dashboard_legacy/static/js/{main.3b27024b.chunk.js.map → main.463c90b9.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/rbac/models.py +1 -0
- zenml/zen_server/rbac/utils.py +4 -0
- zenml/zen_server/routers/pipeline_builds_endpoints.py +2 -66
- zenml/zen_server/routers/pipeline_deployments_endpoints.py +2 -53
- zenml/zen_server/routers/pipelines_endpoints.py +1 -74
- zenml/zen_server/routers/run_templates_endpoints.py +212 -0
- zenml/zen_server/routers/stack_deployment_endpoints.py +6 -0
- zenml/zen_server/routers/users_endpoints.py +0 -7
- zenml/zen_server/routers/workspaces_endpoints.py +79 -0
- zenml/zen_server/{pipeline_deployment → template_execution}/runner_entrypoint_configuration.py +1 -8
- zenml/zen_server/{pipeline_deployment → template_execution}/utils.py +214 -92
- zenml/zen_server/utils.py +77 -2
- zenml/zen_server/zen_server_api.py +54 -2
- zenml/zen_stores/base_zen_store.py +7 -1
- zenml/zen_stores/migrations/versions/0.63.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0.64.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/026d4577b6a0_add_code_path.py +39 -0
- zenml/zen_stores/migrations/versions/3dcc5d20e82f_add_last_user_activity.py +51 -0
- zenml/zen_stores/migrations/versions/7d1919bb1ef0_add_run_templates.py +100 -0
- zenml/zen_stores/migrations/versions/909550c7c4da_remove_user_hub_token.py +36 -0
- zenml/zen_stores/migrations/versions/b59aa68fdb1f_simplify_pipelines.py +139 -0
- zenml/zen_stores/rest_zen_store.py +112 -39
- zenml/zen_stores/schemas/__init__.py +2 -0
- zenml/zen_stores/schemas/pipeline_build_schemas.py +3 -3
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +32 -2
- zenml/zen_stores/schemas/pipeline_run_schemas.py +29 -3
- zenml/zen_stores/schemas/pipeline_schemas.py +29 -30
- zenml/zen_stores/schemas/run_template_schemas.py +264 -0
- zenml/zen_stores/schemas/server_settings_schemas.py +2 -0
- zenml/zen_stores/schemas/step_run_schemas.py +11 -4
- zenml/zen_stores/schemas/user_schemas.py +0 -2
- zenml/zen_stores/sql_zen_store.py +389 -151
- zenml/zen_stores/template_utils.py +261 -0
- zenml/zen_stores/zen_store_interface.py +93 -20
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/METADATA +3 -3
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/RECORD +211 -184
- zenml/_hub/client.py +0 -289
- zenml/_hub/constants.py +0 -21
- zenml/_hub/utils.py +0 -79
- zenml/cli/hub.py +0 -1116
- zenml/models/v2/core/pipeline_namespace.py +0 -113
- zenml/models/v2/misc/hub_plugin_models.py +0 -79
- zenml/new/pipelines/deserialization_utils.py +0 -292
- zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +0 -85
- zenml/zen_server/dashboard/assets/CollapsibleCard-opiuBHHc.js +0 -1
- zenml/zen_server/dashboard/assets/CopyButton-Cr7xYEPb.js +0 -2
- zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +0 -1
- zenml/zen_server/dashboard/assets/Pagination-C6X-mifw.js +0 -1
- zenml/zen_server/dashboard/assets/index-EpMIKgrI.css +0 -1
- zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +0 -1
- zenml/zen_server/dashboard/assets/package-B3fWP-Dh.js +0 -1
- zenml/zen_server/dashboard/assets/page-5NCOHOsy.js +0 -1
- zenml/zen_server/dashboard/assets/page-B6h3iaHJ.js +0 -1
- zenml/zen_server/dashboard/assets/page-Bi-wtWiO.js +0 -5
- zenml/zen_server/dashboard/assets/page-Bq0YxkLV.js +0 -1
- zenml/zen_server/dashboard/assets/page-Bs2F4eoD.js +0 -2
- zenml/zen_server/dashboard/assets/page-CHNxpz3n.js +0 -1
- zenml/zen_server/dashboard/assets/page-DgorQFqi.js +0 -1
- zenml/zen_server/dashboard/assets/page-K8ebxVIs.js +0 -1
- zenml/zen_server/dashboard/assets/page-TgCF0P_U.js +0 -1
- zenml/zen_server/dashboard/assets/page-ZnCEe-eK.js +0 -9
- zenml/zen_server/dashboard/assets/persist-D7HJNBWx.js +0 -1
- zenml/zen_server/dashboard/assets/plus-C8WOyCzt.js +0 -1
- zenml/zen_server/dashboard/assets/secrets-video-OBJ6irhH.svg +0 -21
- zenml/zen_server/dashboard/assets/stacks-video-7gfxpAq4.svg +0 -21
- /zenml/zen_server/{pipeline_deployment → template_execution}/__init__.py +0 -0
- /zenml/zen_server/{pipeline_deployment → template_execution}/workload_manager_interface.py +0 -0
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/entry_points.txt +0 -0
@@ -17,15 +17,17 @@ import re
|
|
17
17
|
from typing import ClassVar, Dict, List
|
18
18
|
|
19
19
|
from zenml.enums import StackDeploymentProvider
|
20
|
+
from zenml.models import StackDeploymentConfig
|
20
21
|
from zenml.stack_deployments.stack_deployment import ZenMLCloudStackDeployment
|
21
22
|
|
23
|
+
AZURE_DEPLOYMENT_TYPE = "azure-cloud-shell"
|
24
|
+
|
22
25
|
|
23
|
-
# TODO: this class just implements the regions list, and is not suitable for other
|
24
|
-
# deployment tasks.
|
25
26
|
class AZUREZenMLCloudStackDeployment(ZenMLCloudStackDeployment):
|
26
27
|
"""Azure ZenML Cloud Stack Deployment."""
|
27
28
|
|
28
29
|
provider: ClassVar[StackDeploymentProvider] = StackDeploymentProvider.AZURE
|
30
|
+
deployment: ClassVar[str] = AZURE_DEPLOYMENT_TYPE
|
29
31
|
|
30
32
|
@classmethod
|
31
33
|
def description(cls) -> str:
|
@@ -37,8 +39,11 @@ class AZUREZenMLCloudStackDeployment(ZenMLCloudStackDeployment):
|
|
37
39
|
Returns:
|
38
40
|
A MarkDown description of the ZenML Cloud Stack Deployment.
|
39
41
|
"""
|
40
|
-
|
41
|
-
|
42
|
+
return """
|
43
|
+
Provision and register a basic Azure ZenML stack authenticated and connected to
|
44
|
+
all the necessary cloud infrastructure resources required to run pipelines in
|
45
|
+
Azure.
|
46
|
+
"""
|
42
47
|
|
43
48
|
@classmethod
|
44
49
|
def instructions(cls) -> str:
|
@@ -51,8 +56,45 @@ class AZUREZenMLCloudStackDeployment(ZenMLCloudStackDeployment):
|
|
51
56
|
MarkDown instructions on how to deploy the ZenML stack to the
|
52
57
|
specified cloud provider.
|
53
58
|
"""
|
54
|
-
|
55
|
-
|
59
|
+
return """
|
60
|
+
You will be redirected to an Azure Cloud Shell console in your browser where
|
61
|
+
you'll be asked to log into your Azure project and then use
|
62
|
+
[the Azure ZenML Stack Terraform module](https://registry.terraform.io/modules/zenml-io/zenml-stack/azure)
|
63
|
+
to provision the necessary cloud resources for ZenML.
|
64
|
+
|
65
|
+
**NOTE**: The Azure ZenML Stack Terraform module will create the following new
|
66
|
+
resources in your Azure subscription. Please ensure you have the necessary
|
67
|
+
permissions and are aware of any potential costs:
|
68
|
+
|
69
|
+
- An Azure Resource Group to contain all the resources required for the ZenML stack
|
70
|
+
- An Azure Storage Account and Blob Storage Container registered as a [ZenML artifact store](https://docs.zenml.io/stack-components/artifact-stores/azure).
|
71
|
+
- An Azure Container Registry registered as a [ZenML container registry](https://docs.zenml.io/stack-components/container-registries/azure).
|
72
|
+
- An AzureML Workspace registered as a [ZenML orchestrator](https://docs.zenml.io/stack-components/orchestrators/azureml) and used to run pipelines.
|
73
|
+
A Key Vault and Application Insights instance will also be created in the same Resource Group and used to construct the AzureML Workspace.
|
74
|
+
- An Azure Service Principal with the minimum necessary permissions to access
|
75
|
+
the above resources.
|
76
|
+
- An Azure Service Principal client secret used to give access to ZenML to
|
77
|
+
connect to the above resources through a [ZenML service connector](https://docs.zenml.io/how-to/auth-management/azure-service-connector).
|
78
|
+
|
79
|
+
The Azure ZenML Stack Terraform module will automatically create an Azure
|
80
|
+
Service Principal client secret and will share it with ZenML to give it
|
81
|
+
permission to access the resources created by the stack. You can revoke these
|
82
|
+
permissions at any time by deleting the Service Principal in your Azure
|
83
|
+
subscription.
|
84
|
+
|
85
|
+
**Estimated costs**
|
86
|
+
|
87
|
+
A small training job would cost around: $0.60
|
88
|
+
|
89
|
+
These are rough estimates and actual costs may vary based on your usage and specific Azure pricing.
|
90
|
+
Some services may be eligible for the Azure Free Tier. Use [the Azure Pricing Calculator](https://azure.microsoft.com/en-us/pricing/calculator)
|
91
|
+
for a detailed estimate based on your usage.
|
92
|
+
|
93
|
+
|
94
|
+
💡 **After the Terraform deployment is complete, you can close the Cloud
|
95
|
+
Shell session and return to the CLI to view details about the associated ZenML
|
96
|
+
stack automatically registered with ZenML.**
|
97
|
+
"""
|
56
98
|
|
57
99
|
@classmethod
|
58
100
|
def post_deploy_instructions(cls) -> str:
|
@@ -64,8 +106,11 @@ class AZUREZenMLCloudStackDeployment(ZenMLCloudStackDeployment):
|
|
64
106
|
MarkDown instructions on what to do after the deployment is
|
65
107
|
complete.
|
66
108
|
"""
|
67
|
-
|
68
|
-
|
109
|
+
return """
|
110
|
+
The ZenML stack has been successfully deployed and registered. You can delete
|
111
|
+
the provisioned Service Principal and Resource Group at any time to revoke
|
112
|
+
ZenML's access to your Azure subscription.
|
113
|
+
"""
|
69
114
|
|
70
115
|
@classmethod
|
71
116
|
def integrations(cls) -> List[str]:
|
@@ -85,8 +130,20 @@ class AZUREZenMLCloudStackDeployment(ZenMLCloudStackDeployment):
|
|
85
130
|
The permissions granted to ZenML to access the cloud resources, as
|
86
131
|
a dictionary grouping permissions by resource.
|
87
132
|
"""
|
88
|
-
|
89
|
-
|
133
|
+
return {
|
134
|
+
"Storage Account": [
|
135
|
+
"Storage Blob Data Contributor",
|
136
|
+
],
|
137
|
+
"Container Registry": [
|
138
|
+
"AcrPull",
|
139
|
+
"AcrPush",
|
140
|
+
"Contributor",
|
141
|
+
],
|
142
|
+
"AzureML Workspace": [
|
143
|
+
"AzureML Compute Operator",
|
144
|
+
"AzureML Data Scientist",
|
145
|
+
],
|
146
|
+
}
|
90
147
|
|
91
148
|
@classmethod
|
92
149
|
def locations(cls) -> Dict[str, str]:
|
@@ -177,3 +234,58 @@ class AZUREZenMLCloudStackDeployment(ZenMLCloudStackDeployment):
|
|
177
234
|
for k, v in cls.locations().items()
|
178
235
|
if "(US)" in k and matcher.match(v)
|
179
236
|
}
|
237
|
+
|
238
|
+
def get_deployment_config(
|
239
|
+
self,
|
240
|
+
) -> StackDeploymentConfig:
|
241
|
+
"""Return the configuration to deploy the ZenML stack to the specified cloud provider.
|
242
|
+
|
243
|
+
The configuration should include:
|
244
|
+
|
245
|
+
* a cloud provider console URL where the user will be redirected to
|
246
|
+
deploy the ZenML stack. The URL should include as many pre-filled
|
247
|
+
URL query parameters as possible.
|
248
|
+
* a textual description of the URL
|
249
|
+
* some deployment providers may require additional configuration
|
250
|
+
parameters or scripts to be passed to the cloud provider in addition to
|
251
|
+
the deployment URL query parameters. Where that is the case, this method
|
252
|
+
should also return a string that the user can copy and paste into the
|
253
|
+
cloud provider console to deploy the ZenML stack (e.g. a set of
|
254
|
+
environment variables, YAML configuration snippet, bash or Terraform
|
255
|
+
script etc.).
|
256
|
+
|
257
|
+
Returns:
|
258
|
+
The configuration or script to deploy the ZenML stack to the
|
259
|
+
specified cloud provider.
|
260
|
+
"""
|
261
|
+
config = f"""module "zenml_stack" {{
|
262
|
+
source = "zenml-io/zenml-stack/azure"
|
263
|
+
|
264
|
+
location = "{self.location or "eastus"}"
|
265
|
+
orchestrator = "azureml"
|
266
|
+
zenml_server_url = "{self.zenml_server_url}"
|
267
|
+
zenml_api_key = ""
|
268
|
+
zenml_api_token = "{self.zenml_server_api_token}"
|
269
|
+
zenml_stack_name = "{self.stack_name}"
|
270
|
+
zenml_stack_deployment = "{self.deployment_type}"
|
271
|
+
}}
|
272
|
+
output "zenml_stack_id" {{
|
273
|
+
value = module.zenml_stack.zenml_stack_id
|
274
|
+
}}
|
275
|
+
output "zenml_stack_name" {{
|
276
|
+
value = module.zenml_stack.zenml_stack_name
|
277
|
+
}}"""
|
278
|
+
instructions = """
|
279
|
+
1. The Azure Cloud Shell console will open in your browser.
|
280
|
+
2. Create a file named `main.tf` in the Cloud Shell and copy and paste the
|
281
|
+
Terraform configuration below into it.
|
282
|
+
3. Run `terraform init --upgrade` to initialize the Terraform configuration.
|
283
|
+
4. Run `terraform apply` to deploy the ZenML stack to Azure.
|
284
|
+
"""
|
285
|
+
|
286
|
+
return StackDeploymentConfig(
|
287
|
+
deployment_url="https://shell.azure.com",
|
288
|
+
deployment_url_text="Azure Cloud Shell Console",
|
289
|
+
configuration=config,
|
290
|
+
instructions=instructions,
|
291
|
+
)
|
@@ -18,7 +18,10 @@ from typing import ClassVar, Dict, List
|
|
18
18
|
|
19
19
|
from zenml.enums import StackDeploymentProvider
|
20
20
|
from zenml.models import StackDeploymentConfig
|
21
|
-
from zenml.stack_deployments.stack_deployment import
|
21
|
+
from zenml.stack_deployments.stack_deployment import (
|
22
|
+
STACK_DEPLOYMENT_TERRAFORM,
|
23
|
+
ZenMLCloudStackDeployment,
|
24
|
+
)
|
22
25
|
|
23
26
|
GCP_DEPLOYMENT_TYPE = "deployment-manager"
|
24
27
|
|
@@ -231,15 +234,16 @@ GCP project and to clean up the resources created by the stack by using
|
|
231
234
|
URL query parameters as possible.
|
232
235
|
* a textual description of the URL
|
233
236
|
* some deployment providers may require additional configuration
|
234
|
-
parameters to be passed to the cloud provider in addition to
|
235
|
-
deployment URL query parameters. Where that is the case, this method
|
237
|
+
parameters or scripts to be passed to the cloud provider in addition to
|
238
|
+
the deployment URL query parameters. Where that is the case, this method
|
236
239
|
should also return a string that the user can copy and paste into the
|
237
240
|
cloud provider console to deploy the ZenML stack (e.g. a set of
|
238
|
-
environment variables,
|
241
|
+
environment variables, YAML configuration snippet, bash or Terraform
|
242
|
+
script etc.).
|
239
243
|
|
240
244
|
Returns:
|
241
|
-
The configuration to deploy the ZenML stack to the
|
242
|
-
provider.
|
245
|
+
The configuration or script to deploy the ZenML stack to the
|
246
|
+
specified cloud provider.
|
243
247
|
"""
|
244
248
|
params = dict(
|
245
249
|
cloudshell_git_repo="https://github.com/zenml-io/zenml",
|
@@ -254,7 +258,26 @@ GCP project and to clean up the resources created by the stack by using
|
|
254
258
|
f"https://shell.cloud.google.com/cloudshell/editor?{query_params}"
|
255
259
|
)
|
256
260
|
|
257
|
-
|
261
|
+
if self.deployment_type == STACK_DEPLOYMENT_TERRAFORM:
|
262
|
+
config = f"""module "zenml_stack" {{
|
263
|
+
source = "zenml-io/zenml-stack/gcp"
|
264
|
+
|
265
|
+
project_id = "my-gcp-project"
|
266
|
+
region = "{self.location or "europe-west3"}"
|
267
|
+
zenml_server_url = "{self.zenml_server_url}"
|
268
|
+
zenml_api_key = ""
|
269
|
+
zenml_api_token = "{self.zenml_server_api_token}"
|
270
|
+
zenml_stack_name = "{self.stack_name}"
|
271
|
+
zenml_stack_deployment = "{self.deployment_type}"
|
272
|
+
}}
|
273
|
+
output "zenml_stack_id" {{
|
274
|
+
value = module.zenml_stack.zenml_stack_id
|
275
|
+
}}
|
276
|
+
output "zenml_stack_name" {{
|
277
|
+
value = module.zenml_stack.zenml_stack_name
|
278
|
+
}}"""
|
279
|
+
else:
|
280
|
+
config = f"""
|
258
281
|
### BEGIN CONFIGURATION ###
|
259
282
|
ZENML_STACK_NAME={self.stack_name}
|
260
283
|
ZENML_STACK_REGION={self.location or "europe-west3"}
|
@@ -262,8 +285,14 @@ ZENML_SERVER_URL={self.zenml_server_url}
|
|
262
285
|
ZENML_SERVER_API_TOKEN={self.zenml_server_api_token}
|
263
286
|
### END CONFIGURATION ###"""
|
264
287
|
|
288
|
+
instructions = (
|
289
|
+
"You will be asked to provide the following configuration values "
|
290
|
+
"during the deployment process:"
|
291
|
+
)
|
292
|
+
|
265
293
|
return StackDeploymentConfig(
|
266
294
|
deployment_url=url,
|
267
295
|
deployment_url_text="GCP Cloud Shell Console",
|
268
296
|
configuration=config,
|
297
|
+
instructions=instructions,
|
269
298
|
)
|
@@ -27,12 +27,15 @@ from zenml.models import (
|
|
27
27
|
StackDeploymentInfo,
|
28
28
|
)
|
29
29
|
|
30
|
+
STACK_DEPLOYMENT_TERRAFORM = "terraform"
|
31
|
+
|
30
32
|
|
31
33
|
class ZenMLCloudStackDeployment(BaseModel):
|
32
34
|
"""ZenML Cloud Stack CLI Deployment base class."""
|
33
35
|
|
34
36
|
provider: ClassVar[StackDeploymentProvider]
|
35
37
|
deployment: ClassVar[str]
|
38
|
+
terraform: bool = False
|
36
39
|
stack_name: str
|
37
40
|
zenml_server_url: str
|
38
41
|
zenml_server_api_token: str
|
@@ -105,6 +108,17 @@ class ZenMLCloudStackDeployment(BaseModel):
|
|
105
108
|
names to region descriptions.
|
106
109
|
"""
|
107
110
|
|
111
|
+
@property
|
112
|
+
def deployment_type(self) -> str:
|
113
|
+
"""Return the type of deployment.
|
114
|
+
|
115
|
+
Returns:
|
116
|
+
The type of deployment.
|
117
|
+
"""
|
118
|
+
if self.terraform:
|
119
|
+
return STACK_DEPLOYMENT_TERRAFORM
|
120
|
+
return self.deployment
|
121
|
+
|
108
122
|
@classmethod
|
109
123
|
def skypilot_default_regions(cls) -> Dict[str, str]:
|
110
124
|
"""Returns the regions supported by default for the Skypilot.
|
@@ -145,19 +159,21 @@ class ZenMLCloudStackDeployment(BaseModel):
|
|
145
159
|
URL query parameters as possible.
|
146
160
|
* a textual description of the URL
|
147
161
|
* some deployment providers may require additional configuration
|
148
|
-
parameters to be passed to the cloud provider in addition to
|
149
|
-
deployment URL query parameters. Where that is the case, this method
|
162
|
+
parameters or scripts to be passed to the cloud provider in addition to
|
163
|
+
the deployment URL query parameters. Where that is the case, this method
|
150
164
|
should also return a string that the user can copy and paste into the
|
151
165
|
cloud provider console to deploy the ZenML stack (e.g. a set of
|
152
|
-
environment variables,
|
166
|
+
environment variables, YAML configuration snippet, bash or Terraform
|
167
|
+
script etc.).
|
153
168
|
|
154
169
|
Returns:
|
155
|
-
The configuration to deploy the ZenML stack to the
|
156
|
-
provider.
|
170
|
+
The configuration or script to deploy the ZenML stack to the
|
171
|
+
specified cloud provider.
|
157
172
|
"""
|
158
173
|
|
159
174
|
def get_stack(
|
160
|
-
self,
|
175
|
+
self,
|
176
|
+
date_start: Optional[datetime.datetime] = None,
|
161
177
|
) -> Optional[DeployedStack]:
|
162
178
|
"""Return the ZenML stack that was deployed and registered.
|
163
179
|
|
@@ -200,7 +216,7 @@ class ZenMLCloudStackDeployment(BaseModel):
|
|
200
216
|
if stack.labels.get("zenml:provider") != self.provider.value:
|
201
217
|
continue
|
202
218
|
|
203
|
-
if stack.labels.get("zenml:deployment") != self.
|
219
|
+
if stack.labels.get("zenml:deployment") != self.deployment_type:
|
204
220
|
continue
|
205
221
|
|
206
222
|
artifact_store = stack.components[
|
zenml/steps/base_step.py
CHANGED
@@ -54,6 +54,7 @@ from zenml.steps.utils import (
|
|
54
54
|
)
|
55
55
|
from zenml.utils import (
|
56
56
|
dict_utils,
|
57
|
+
notebook_utils,
|
57
58
|
pydantic_utils,
|
58
59
|
settings_utils,
|
59
60
|
source_code_utils,
|
@@ -249,6 +250,8 @@ class BaseStep(metaclass=BaseStepMeta):
|
|
249
250
|
)
|
250
251
|
self._verify_and_apply_init_params(*args, **kwargs)
|
251
252
|
|
253
|
+
notebook_utils.try_to_save_notebook_cell_code(self.source_object)
|
254
|
+
|
252
255
|
@abstractmethod
|
253
256
|
def entrypoint(self, *args: Any, **kwargs: Any) -> Any:
|
254
257
|
"""Abstract method for core step logic.
|
zenml/steps/utils.py
CHANGED
@@ -413,7 +413,6 @@ def log_step_metadata(
|
|
413
413
|
metadata: Dict[str, "MetadataType"],
|
414
414
|
step_name: Optional[str] = None,
|
415
415
|
pipeline_name_id_or_prefix: Optional[Union[str, UUID]] = None,
|
416
|
-
pipeline_version: Optional[str] = None,
|
417
416
|
run_id: Optional[str] = None,
|
418
417
|
) -> None:
|
419
418
|
"""Logs step metadata.
|
@@ -424,8 +423,6 @@ def log_step_metadata(
|
|
424
423
|
when being called inside a step.
|
425
424
|
pipeline_name_id_or_prefix: The name of the pipeline to log metadata
|
426
425
|
for. Can be omitted when being called inside a step.
|
427
|
-
pipeline_version: The version of the pipeline to log metadata for.
|
428
|
-
Can be omitted when being called inside a step.
|
429
426
|
run_id: The ID of the run to log metadata for. Can be omitted when
|
430
427
|
being called inside a step.
|
431
428
|
|
@@ -460,7 +457,6 @@ def log_step_metadata(
|
|
460
457
|
)
|
461
458
|
pipeline_run = client.get_pipeline(
|
462
459
|
name_id_or_prefix=pipeline_name_id_or_prefix,
|
463
|
-
version=pipeline_version,
|
464
460
|
).last_run
|
465
461
|
step_run_id = pipeline_run.steps[step_name].id
|
466
462
|
client.create_run_metadata(
|
@@ -0,0 +1,149 @@
|
|
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
|
+
"""Archivable mixin."""
|
15
|
+
|
16
|
+
import io
|
17
|
+
import tarfile
|
18
|
+
from abc import ABC, abstractmethod
|
19
|
+
from pathlib import Path
|
20
|
+
from typing import IO, Any, Dict
|
21
|
+
|
22
|
+
from zenml.io import fileio
|
23
|
+
|
24
|
+
|
25
|
+
class Archivable(ABC):
|
26
|
+
"""Archivable mixin class."""
|
27
|
+
|
28
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
29
|
+
"""Initialize the object.
|
30
|
+
|
31
|
+
Args:
|
32
|
+
*args: Unused args for subclasses.
|
33
|
+
**kwargs: Unused keyword args for subclasses.
|
34
|
+
"""
|
35
|
+
self._extra_files: Dict[str, str] = {}
|
36
|
+
|
37
|
+
def add_file(self, source: str, destination: str) -> None:
|
38
|
+
"""Adds a file to the archive.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
source: The source of the file to add. This can either be a path
|
42
|
+
or the file content.
|
43
|
+
destination: The path inside the archive where the file
|
44
|
+
should be added.
|
45
|
+
"""
|
46
|
+
if fileio.exists(source):
|
47
|
+
with fileio.open(source) as f:
|
48
|
+
self._extra_files[destination] = f.read()
|
49
|
+
else:
|
50
|
+
self._extra_files[destination] = source
|
51
|
+
|
52
|
+
def add_directory(self, source: str, destination: str) -> None:
|
53
|
+
"""Adds a directory to the archive.
|
54
|
+
|
55
|
+
Args:
|
56
|
+
source: Path to the directory.
|
57
|
+
destination: The path inside the build context where the directory
|
58
|
+
should be added.
|
59
|
+
|
60
|
+
Raises:
|
61
|
+
ValueError: If `source` does not point to a directory.
|
62
|
+
"""
|
63
|
+
if not fileio.isdir(source):
|
64
|
+
raise ValueError(
|
65
|
+
f"Can't add directory {source} to the build context as it "
|
66
|
+
"does not exist or is not a directory."
|
67
|
+
)
|
68
|
+
|
69
|
+
for dir, _, files in fileio.walk(source):
|
70
|
+
dir_path = Path(fileio.convert_to_str(dir))
|
71
|
+
for file_name in files:
|
72
|
+
file_name = fileio.convert_to_str(file_name)
|
73
|
+
file_source = dir_path / file_name
|
74
|
+
file_destination = (
|
75
|
+
Path(destination)
|
76
|
+
/ dir_path.relative_to(source)
|
77
|
+
/ file_name
|
78
|
+
)
|
79
|
+
|
80
|
+
with file_source.open("r") as f:
|
81
|
+
self._extra_files[file_destination.as_posix()] = f.read()
|
82
|
+
|
83
|
+
def write_archive(
|
84
|
+
self, output_file: IO[bytes], use_gzip: bool = True
|
85
|
+
) -> None:
|
86
|
+
"""Writes an archive of the build context to the given file.
|
87
|
+
|
88
|
+
Args:
|
89
|
+
output_file: The file to write the archive to.
|
90
|
+
use_gzip: Whether to use `gzip` to compress the file.
|
91
|
+
"""
|
92
|
+
files = self.get_files()
|
93
|
+
extra_files = self.get_extra_files()
|
94
|
+
|
95
|
+
if use_gzip:
|
96
|
+
from gzip import GzipFile
|
97
|
+
|
98
|
+
# We don't use the builtin gzip functionality of the `tarfile`
|
99
|
+
# library as that one includes the tar filename and creation
|
100
|
+
# timestamp in the archive which causes the hash of the resulting
|
101
|
+
# file to be different each time. We use this hash to avoid
|
102
|
+
# duplicate uploads, which is why we pass empty values for filename
|
103
|
+
# and mtime here.
|
104
|
+
fileobj: Any = GzipFile(
|
105
|
+
filename="", mode="wb", fileobj=output_file, mtime=0.0
|
106
|
+
)
|
107
|
+
else:
|
108
|
+
fileobj = output_file
|
109
|
+
|
110
|
+
with tarfile.open(mode="w", fileobj=fileobj) as tf:
|
111
|
+
for archive_path, file_path in files.items():
|
112
|
+
if archive_path in extra_files:
|
113
|
+
continue
|
114
|
+
|
115
|
+
if info := tf.gettarinfo(file_path, arcname=archive_path):
|
116
|
+
if info.isfile():
|
117
|
+
with open(file_path, "rb") as f:
|
118
|
+
tf.addfile(info, f)
|
119
|
+
else:
|
120
|
+
tf.addfile(info, None)
|
121
|
+
|
122
|
+
for archive_path, contents in extra_files.items():
|
123
|
+
info = tarfile.TarInfo(archive_path)
|
124
|
+
contents_encoded = contents.encode("utf-8")
|
125
|
+
info.size = len(contents_encoded)
|
126
|
+
tf.addfile(info, io.BytesIO(contents_encoded))
|
127
|
+
|
128
|
+
if use_gzip:
|
129
|
+
fileobj.close()
|
130
|
+
|
131
|
+
output_file.seek(0)
|
132
|
+
|
133
|
+
@abstractmethod
|
134
|
+
def get_files(self) -> Dict[str, str]:
|
135
|
+
"""Gets all regular files that should be included in the archive.
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
A dict {path_in_archive: path_on_filesystem} for all regular files
|
139
|
+
in the archive.
|
140
|
+
"""
|
141
|
+
|
142
|
+
def get_extra_files(self) -> Dict[str, str]:
|
143
|
+
"""Gets all extra files that should be included in the archive.
|
144
|
+
|
145
|
+
Returns:
|
146
|
+
A dict {path_in_archive: file_content} for all extra files in the
|
147
|
+
archive.
|
148
|
+
"""
|
149
|
+
return self._extra_files.copy()
|