zenml-nightly 0.60.0.dev20240627__py3-none-any.whl → 0.61.0.dev20240711__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 +34 -0
- zenml/VERSION +1 -1
- 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 +797 -39
- zenml/cli/stack_components.py +7 -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 +5 -1
- zenml/container_registries/base_container_registry.py +1 -0
- zenml/enums.py +6 -0
- zenml/event_hub/event_hub.py +5 -8
- zenml/integrations/aws/__init__.py +1 -0
- zenml/integrations/azure/__init__.py +1 -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/service_connectors/gcp_service_connector.py +203 -44
- 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 +3 -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 -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/models/__init__.py +9 -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/misc/full_stack.py +97 -0
- zenml/models/v2/misc/stack_deployment.py +66 -0
- zenml/new/pipelines/pipeline.py +1 -1
- zenml/orchestrators/input_utils.py +3 -6
- zenml/stack/stack.py +3 -6
- zenml/stack_deployments/__init__.py +14 -0
- zenml/stack_deployments/aws_stack_deployment.py +289 -0
- zenml/stack_deployments/stack_deployment.py +130 -0
- zenml/stack_deployments/utils.py +40 -0
- zenml/utils/function_utils.py +1 -1
- zenml/utils/pagination_utils.py +7 -5
- zenml/utils/pipeline_docker_image_builder.py +97 -68
- zenml/utils/pydantic_utils.py +6 -5
- zenml/zen_server/cloud_utils.py +18 -3
- zenml/zen_server/dashboard/assets/{404-C1mcUujL.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-DYIyhCfd.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-WEzpO0az.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-Bx931j4U.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-CKrd3UZz.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-Bk2tn324.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-D12Rvf0j.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-8vRWJ5b8.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-CBuSUrE9.js → page-CRTJ0UuR.js} +1 -1
- 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-CCtCgG-x.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-Dw9-aJV6.js → page-DKlIdAe5.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-COafKNbw.js → page-DMOYZppS.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +2 -0
- zenml/zen_server/dashboard/assets/{page-C6v3o0Qj.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-CH26py0a.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-bKxf7U9h.js → update-server-settings-mutation-CR8e3Sir.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-CgvM-IVM.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.e7c29295aae591541ef59d1734d79387.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.53857d8b.chunk.js → main.382439a7.chunk.js} +2 -2
- zenml/zen_server/dashboard_legacy/static/js/{main.53857d8b.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/zenml_cloud_rbac.py +11 -5
- zenml/zen_server/routers/stack_deployment_endpoints.py +144 -0
- 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.61.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
- zenml/zen_stores/rest_zen_store.py +117 -0
- 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 +283 -0
- zenml/zen_stores/zen_store_interface.py +79 -0
- {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240711.dist-info}/METADATA +32 -10
- {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240711.dist-info}/RECORD +175 -161
- 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-B2KR83Tr.js +0 -1
- zenml/zen_server/dashboard/assets/Cards-DSEdjsk8.js +0 -1
- zenml/zen_server/dashboard/assets/Commands-CTlhyic5.js +0 -1
- zenml/zen_server/dashboard/assets/CopyButton-CTrzKmUO.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-4sKxHad4.js +0 -1
- zenml/zen_server/dashboard/assets/Helpbox-DW21i5LD.js +0 -1
- zenml/zen_server/dashboard/assets/Infobox-C7bf70VS.js +0 -1
- zenml/zen_server/dashboard/assets/InlineAvatar-Dxrtafpg.js +0 -1
- zenml/zen_server/dashboard/assets/PageHeader-B0pUife2.js +0 -1
- zenml/zen_server/dashboard/assets/Pagination-B9WG_9cJ.js +0 -1
- zenml/zen_server/dashboard/assets/PasswordChecker-DSLBp7Vl.js +0 -1
- zenml/zen_server/dashboard/assets/SetPassword-CiNhT15a.js +0 -1
- zenml/zen_server/dashboard/assets/SuccessStep-CykrFndS.js +0 -1
- zenml/zen_server/dashboard/assets/cloud-only-Bkawp7CJ.js +0 -1
- zenml/zen_server/dashboard/assets/index-BawkpTlr.js +0 -55
- zenml/zen_server/dashboard/assets/index-CRmm7QhS.css +0 -1
- zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +0 -1
- zenml/zen_server/dashboard/assets/not-found-BAuhP4Jb.js +0 -1
- zenml/zen_server/dashboard/assets/page--5YvAHg3.js +0 -1
- zenml/zen_server/dashboard/assets/page-B0RAq4s_.js +0 -1
- zenml/zen_server/dashboard/assets/page-BePtEPHl.js +0 -1
- zenml/zen_server/dashboard/assets/page-C1pra1Bc.js +0 -9
- zenml/zen_server/dashboard/assets/page-CSs4C9jL.js +0 -1
- zenml/zen_server/dashboard/assets/page-Cf2XSej0.js +0 -1
- zenml/zen_server/dashboard/assets/page-ClPUAE_f.js +0 -1
- zenml/zen_server/dashboard/assets/page-D8pf2vis.js +0 -1
- zenml/zen_server/dashboard/assets/page-DHKMmIQH.js +0 -1
- zenml/zen_server/dashboard/assets/page-DMZ0VOda.js +0 -1
- zenml/zen_server/dashboard/assets/page-Dcg-yQv_.js +0 -1
- zenml/zen_server/dashboard/assets/page-DoAK5FSB.js +0 -1
- zenml/zen_server/dashboard/assets/page-iXiDqE0J.js +0 -2
- {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240711.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240711.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240711.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,289 @@
|
|
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
|
+
"""Functionality to deploy a ZenML stack to a cloud provider."""
|
15
|
+
|
16
|
+
import datetime
|
17
|
+
from typing import ClassVar, Dict, List, Optional, Tuple
|
18
|
+
|
19
|
+
from zenml.client import Client
|
20
|
+
from zenml.enums import StackComponentType, StackDeploymentProvider
|
21
|
+
from zenml.models import (
|
22
|
+
DeployedStack,
|
23
|
+
)
|
24
|
+
from zenml.stack_deployments.stack_deployment import ZenMLCloudStackDeployment
|
25
|
+
from zenml.utils.string_utils import random_str
|
26
|
+
|
27
|
+
AWS_DEPLOYMENT_TYPE = "cloud-formation"
|
28
|
+
|
29
|
+
|
30
|
+
class AWSZenMLCloudStackDeployment(ZenMLCloudStackDeployment):
|
31
|
+
"""AWS ZenML Cloud Stack Deployment."""
|
32
|
+
|
33
|
+
provider: ClassVar[StackDeploymentProvider] = StackDeploymentProvider.AWS
|
34
|
+
|
35
|
+
@classmethod
|
36
|
+
def description(cls) -> str:
|
37
|
+
"""Return a description of the ZenML Cloud Stack Deployment.
|
38
|
+
|
39
|
+
This will be displayed when the user is prompted to deploy
|
40
|
+
the ZenML stack.
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
A MarkDown description of the ZenML Cloud Stack Deployment.
|
44
|
+
"""
|
45
|
+
return """
|
46
|
+
Provision and register a basic AWS ZenML stack authenticated and connected to
|
47
|
+
all the necessary cloud infrastructure resources required to run pipelines in
|
48
|
+
AWS.
|
49
|
+
"""
|
50
|
+
|
51
|
+
@classmethod
|
52
|
+
def instructions(cls) -> str:
|
53
|
+
"""Return instructions on how to deploy the ZenML stack to the specified cloud provider.
|
54
|
+
|
55
|
+
This will be displayed before the user is prompted to deploy the ZenML
|
56
|
+
stack.
|
57
|
+
|
58
|
+
Returns:
|
59
|
+
MarkDown instructions on how to deploy the ZenML stack to the
|
60
|
+
specified cloud provider.
|
61
|
+
"""
|
62
|
+
return """
|
63
|
+
You will be redirected to the AWS console in your browser where you'll be asked
|
64
|
+
to log into your AWS account and create a CloudFormation ZenML stack. The stack
|
65
|
+
parameters will be pre-filled with the necessary information to connect ZenML to
|
66
|
+
your AWS account, so you should only need to review and confirm the stack.
|
67
|
+
|
68
|
+
After the CloudFormation stack is deployed, you can return to the CLI to view
|
69
|
+
details about the associated ZenML stack automatically registered with ZenML.
|
70
|
+
|
71
|
+
**NOTE**: The CloudFormation stack will create the following new resources in
|
72
|
+
your AWS account. Please ensure you have the necessary permissions and are aware
|
73
|
+
of any potential costs:
|
74
|
+
|
75
|
+
- An S3 bucket registered as a [ZenML artifact store](https://docs.zenml.io/stack-components/artifact-stores/s3).
|
76
|
+
- An ECR repository registered as a [ZenML container registry](https://docs.zenml.io/stack-components/container-registries/aws).
|
77
|
+
- Sagemaker registered as a [ZenML orchestrator](https://docs.zenml.io/stack-components/orchestrators/sagemaker).
|
78
|
+
- An IAM user and IAM role with the minimum necessary permissions to access the
|
79
|
+
above resources.
|
80
|
+
- An AWS access key used to give access to ZenML to connect to the above
|
81
|
+
resources through a [ZenML service connector](https://docs.zenml.io/how-to/auth-management/aws-service-connector).
|
82
|
+
|
83
|
+
The CloudFormation stack will automatically create an AWS secret key and
|
84
|
+
will share it with ZenML to give it permission to access the resources created
|
85
|
+
by the stack. You can revoke these permissions at any time by deleting the
|
86
|
+
CloudFormation stack.
|
87
|
+
"""
|
88
|
+
|
89
|
+
@classmethod
|
90
|
+
def post_deploy_instructions(cls) -> str:
|
91
|
+
"""Return instructions on what to do after the deployment is complete.
|
92
|
+
|
93
|
+
This will be displayed after the deployment is complete.
|
94
|
+
|
95
|
+
Returns:
|
96
|
+
MarkDown instructions on what to do after the deployment is
|
97
|
+
complete.
|
98
|
+
"""
|
99
|
+
return """
|
100
|
+
The ZenML stack has been successfully deployed and registered. You can delete
|
101
|
+
the CloudFormation at any time to revoke ZenML's access to your AWS account and
|
102
|
+
to clean up the resources created by the stack by using the AWS CloudFormation
|
103
|
+
console.
|
104
|
+
"""
|
105
|
+
|
106
|
+
@classmethod
|
107
|
+
def permissions(cls) -> Dict[str, List[str]]:
|
108
|
+
"""Return the permissions granted to ZenML to access the cloud resources.
|
109
|
+
|
110
|
+
Returns:
|
111
|
+
The permissions granted to ZenML to access the cloud resources, as
|
112
|
+
a dictionary grouping permissions by resource.
|
113
|
+
"""
|
114
|
+
return {
|
115
|
+
"S3 Bucket": [
|
116
|
+
"s3:ListBucket",
|
117
|
+
"s3:GetObject",
|
118
|
+
"s3:PutObject",
|
119
|
+
"s3:DeleteObject",
|
120
|
+
],
|
121
|
+
"ECR Repository": [
|
122
|
+
"ecr:DescribeRepositories",
|
123
|
+
"ecr:ListRepositories",
|
124
|
+
"ecr:DescribeRegistry",
|
125
|
+
"ecr:BatchGetImage",
|
126
|
+
"ecr:DescribeImages",
|
127
|
+
"ecr:BatchCheckLayerAvailability",
|
128
|
+
"ecr:GetDownloadUrlForLayer",
|
129
|
+
"ecr:InitiateLayerUpload",
|
130
|
+
"ecr:UploadLayerPart",
|
131
|
+
"ecr:CompleteLayerUpload",
|
132
|
+
"ecr:PutImage",
|
133
|
+
"ecr:GetAuthorizationToken",
|
134
|
+
],
|
135
|
+
"SageMaker (Client)": [
|
136
|
+
"sagemaker:CreatePipeline",
|
137
|
+
"sagemaker:StartPipelineExecution",
|
138
|
+
"sagemaker:DescribePipeline",
|
139
|
+
"sagemaker:DescribePipelineExecution",
|
140
|
+
],
|
141
|
+
"SageMaker (Jobs)": [
|
142
|
+
"AmazonSageMakerFullAccess",
|
143
|
+
],
|
144
|
+
}
|
145
|
+
|
146
|
+
@classmethod
|
147
|
+
def locations(cls) -> Dict[str, str]:
|
148
|
+
"""Return the locations where the ZenML stack can be deployed.
|
149
|
+
|
150
|
+
Returns:
|
151
|
+
The regions where the ZenML stack can be deployed as a map of region
|
152
|
+
names to region descriptions.
|
153
|
+
"""
|
154
|
+
# Return a list of all possible AWS regions
|
155
|
+
|
156
|
+
# Based on the AWS regions listed at
|
157
|
+
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html
|
158
|
+
return {
|
159
|
+
"US East (Ohio)": "us-east-2",
|
160
|
+
"US East (N. Virginia)": "us-east-1",
|
161
|
+
"US West (N. California)": "us-west-1",
|
162
|
+
"US West (Oregon)": "us-west-2",
|
163
|
+
"Africa (Cape Town)": "af-south-1",
|
164
|
+
"Asia Pacific (Hong Kong)": "ap-east-1",
|
165
|
+
"Asia Pacific (Hyderabad)": "ap-south-2",
|
166
|
+
"Asia Pacific (Jakarta)": "ap-southeast-3",
|
167
|
+
"Asia Pacific (Melbourne)": "ap-southeast-4",
|
168
|
+
"Asia Pacific (Mumbai)": "ap-south-1",
|
169
|
+
"Asia Pacific (Osaka)": "ap-northeast-3",
|
170
|
+
"Asia Pacific (Seoul)": "ap-northeast-2",
|
171
|
+
"Asia Pacific (Singapore)": "ap-southeast-1",
|
172
|
+
"Asia Pacific (Sydney)": "ap-southeast-2",
|
173
|
+
"Asia Pacific (Tokyo)": "ap-northeast-1",
|
174
|
+
"Canada (Central)": "ca-central-1",
|
175
|
+
"Canada West (Calgary)": "ca-west-1",
|
176
|
+
"Europe (Frankfurt)": "eu-central-1",
|
177
|
+
"Europe (Ireland)": "eu-west-1",
|
178
|
+
"Europe (London)": "eu-west-2",
|
179
|
+
"Europe (Milan)": "eu-south-1",
|
180
|
+
"Europe (Paris)": "eu-west-3",
|
181
|
+
"Europe (Spain)": "eu-south-2",
|
182
|
+
"Europe (Stockholm)": "eu-north-1",
|
183
|
+
"Europe (Zurich)": "eu-central-2",
|
184
|
+
"Israel (Tel Aviv)": "il-central-1",
|
185
|
+
"Middle East (Bahrain)": "me-south-1",
|
186
|
+
"Middle East (UAE)": "me-central-1",
|
187
|
+
"South America (São Paulo)": "sa-east-1",
|
188
|
+
}
|
189
|
+
|
190
|
+
def deploy_url(
|
191
|
+
self,
|
192
|
+
zenml_server_url: str,
|
193
|
+
zenml_server_api_token: str,
|
194
|
+
) -> Tuple[str, str]:
|
195
|
+
"""Return the URL to deploy the ZenML stack to the specified cloud provider.
|
196
|
+
|
197
|
+
The URL should point to a cloud provider console where the user can
|
198
|
+
deploy the ZenML stack and should include as many pre-filled parameters
|
199
|
+
as possible.
|
200
|
+
|
201
|
+
Args:
|
202
|
+
zenml_server_url: The URL of the ZenML server.
|
203
|
+
zenml_server_api_token: The API token to authenticate with the ZenML
|
204
|
+
server.
|
205
|
+
|
206
|
+
Returns:
|
207
|
+
The URL to deploy the ZenML stack to the specified cloud provider
|
208
|
+
and a text description of the URL.
|
209
|
+
"""
|
210
|
+
params = dict(
|
211
|
+
stackName=self.stack_name,
|
212
|
+
templateURL="https://zenml-cf-templates.s3.eu-central-1.amazonaws.com/aws-ecr-s3-sagemaker.yaml",
|
213
|
+
param_ResourceName=f"zenml-{random_str(6).lower()}",
|
214
|
+
param_ZenMLServerURL=zenml_server_url,
|
215
|
+
param_ZenMLServerAPIToken=zenml_server_api_token,
|
216
|
+
)
|
217
|
+
# Encode the parameters as URL query parameters
|
218
|
+
query_params = "&".join([f"{k}={v}" for k, v in params.items()])
|
219
|
+
|
220
|
+
region = ""
|
221
|
+
if self.location:
|
222
|
+
region = f"region={self.location}"
|
223
|
+
|
224
|
+
return (
|
225
|
+
f"https://console.aws.amazon.com/cloudformation/home?"
|
226
|
+
f"{region}#/stacks/create/review?{query_params}",
|
227
|
+
"AWS CloudFormation Console",
|
228
|
+
)
|
229
|
+
|
230
|
+
def get_stack(
|
231
|
+
self, date_start: Optional[datetime.datetime] = None
|
232
|
+
) -> Optional[DeployedStack]:
|
233
|
+
"""Return the ZenML stack that was deployed and registered.
|
234
|
+
|
235
|
+
This method is called to retrieve a ZenML stack matching the deployment
|
236
|
+
provider.
|
237
|
+
|
238
|
+
Args:
|
239
|
+
date_start: The date when the deployment started.
|
240
|
+
|
241
|
+
Returns:
|
242
|
+
The ZenML stack that was deployed and registered or None if a
|
243
|
+
matching stack was not found.
|
244
|
+
"""
|
245
|
+
client = Client()
|
246
|
+
|
247
|
+
# It's difficult to find a stack that matches the CloudFormation
|
248
|
+
# deployment 100% because the user can change the stack name before they
|
249
|
+
# deploy the stack in AWS.
|
250
|
+
#
|
251
|
+
# We try to find a full AWS stack that matches the deployment provider
|
252
|
+
# that was registered after this deployment was created.
|
253
|
+
|
254
|
+
# Get all stacks created after the start date
|
255
|
+
stacks = client.list_stacks(
|
256
|
+
created=f"gt:{str(date_start.replace(microsecond=0))}"
|
257
|
+
if date_start
|
258
|
+
else None,
|
259
|
+
sort_by="desc:created",
|
260
|
+
size=50,
|
261
|
+
)
|
262
|
+
|
263
|
+
if not stacks.items:
|
264
|
+
return None
|
265
|
+
|
266
|
+
# Find a stack that best matches the deployment provider
|
267
|
+
for stack in stacks.items:
|
268
|
+
if not stack.labels:
|
269
|
+
continue
|
270
|
+
|
271
|
+
if stack.labels.get("zenml:provider") != self.provider.value:
|
272
|
+
continue
|
273
|
+
|
274
|
+
if stack.labels.get("zenml:deployment") != AWS_DEPLOYMENT_TYPE:
|
275
|
+
continue
|
276
|
+
|
277
|
+
artifact_store = stack.components[
|
278
|
+
StackComponentType.ARTIFACT_STORE
|
279
|
+
][0]
|
280
|
+
|
281
|
+
if not artifact_store.connector:
|
282
|
+
continue
|
283
|
+
|
284
|
+
return DeployedStack(
|
285
|
+
stack=stack,
|
286
|
+
service_connector=artifact_store.connector,
|
287
|
+
)
|
288
|
+
|
289
|
+
return None
|
@@ -0,0 +1,130 @@
|
|
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
|
+
"""Functionality to deploy a ZenML stack to a cloud provider."""
|
15
|
+
|
16
|
+
import datetime
|
17
|
+
from abc import abstractmethod
|
18
|
+
from typing import ClassVar, Dict, List, Optional, Tuple
|
19
|
+
|
20
|
+
from pydantic import BaseModel
|
21
|
+
|
22
|
+
from zenml.enums import StackDeploymentProvider
|
23
|
+
from zenml.models import (
|
24
|
+
DeployedStack,
|
25
|
+
)
|
26
|
+
|
27
|
+
|
28
|
+
class ZenMLCloudStackDeployment(BaseModel):
|
29
|
+
"""ZenML Cloud Stack CLI Deployment base class."""
|
30
|
+
|
31
|
+
provider: ClassVar[StackDeploymentProvider]
|
32
|
+
stack_name: str
|
33
|
+
location: Optional[str] = None
|
34
|
+
|
35
|
+
@classmethod
|
36
|
+
@abstractmethod
|
37
|
+
def description(cls) -> str:
|
38
|
+
"""Return a description of the ZenML Cloud Stack Deployment.
|
39
|
+
|
40
|
+
This will be displayed when the user is prompted to deploy
|
41
|
+
the ZenML stack.
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
A MarkDown description of the ZenML Cloud Stack Deployment.
|
45
|
+
"""
|
46
|
+
|
47
|
+
@classmethod
|
48
|
+
@abstractmethod
|
49
|
+
def instructions(cls) -> str:
|
50
|
+
"""Return instructions on how to deploy the ZenML stack to the specified cloud provider.
|
51
|
+
|
52
|
+
This will be displayed before the user is prompted to deploy the ZenML
|
53
|
+
stack.
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
MarkDown instructions on how to deploy the ZenML stack to the
|
57
|
+
specified cloud provider.
|
58
|
+
"""
|
59
|
+
|
60
|
+
@classmethod
|
61
|
+
@abstractmethod
|
62
|
+
def post_deploy_instructions(cls) -> str:
|
63
|
+
"""Return instructions on what to do after the deployment is complete.
|
64
|
+
|
65
|
+
This will be displayed after the deployment is complete.
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
MarkDown instructions on what to do after the deployment is
|
69
|
+
complete.
|
70
|
+
"""
|
71
|
+
|
72
|
+
@classmethod
|
73
|
+
@abstractmethod
|
74
|
+
def permissions(cls) -> Dict[str, List[str]]:
|
75
|
+
"""Return the permissions granted to ZenML to access the cloud resources.
|
76
|
+
|
77
|
+
Returns:
|
78
|
+
The permissions granted to ZenML to access the cloud resources, as
|
79
|
+
a dictionary grouping permissions by resource.
|
80
|
+
"""
|
81
|
+
|
82
|
+
@classmethod
|
83
|
+
@abstractmethod
|
84
|
+
def locations(cls) -> Dict[str, str]:
|
85
|
+
"""Return the locations where the ZenML stack can be deployed.
|
86
|
+
|
87
|
+
Returns:
|
88
|
+
The regions where the ZenML stack can be deployed as a map of region
|
89
|
+
names to region descriptions.
|
90
|
+
"""
|
91
|
+
|
92
|
+
@abstractmethod
|
93
|
+
def deploy_url(
|
94
|
+
self,
|
95
|
+
zenml_server_url: str,
|
96
|
+
zenml_server_api_token: str,
|
97
|
+
) -> Tuple[str, str]:
|
98
|
+
"""Return the URL to deploy the ZenML stack to the specified cloud provider.
|
99
|
+
|
100
|
+
The URL should point to a cloud provider console where the user can
|
101
|
+
deploy the ZenML stack and should include as many pre-filled parameters
|
102
|
+
as possible.
|
103
|
+
|
104
|
+
Args:
|
105
|
+
zenml_server_url: The URL of the ZenML server.
|
106
|
+
zenml_server_api_token: The API token to authenticate with the ZenML
|
107
|
+
server.
|
108
|
+
|
109
|
+
Returns:
|
110
|
+
The URL to deploy the ZenML stack to the specified cloud provider
|
111
|
+
and a text description of the URL.
|
112
|
+
"""
|
113
|
+
|
114
|
+
@abstractmethod
|
115
|
+
def get_stack(
|
116
|
+
self,
|
117
|
+
date_start: Optional[datetime.datetime] = None,
|
118
|
+
) -> Optional[DeployedStack]:
|
119
|
+
"""Return the ZenML stack that was deployed and registered.
|
120
|
+
|
121
|
+
This method is called to retrieve a ZenML stack matching the deployment
|
122
|
+
provider and stack name.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
date_start: The start date of the deployment.
|
126
|
+
|
127
|
+
Returns:
|
128
|
+
The ZenML stack that was deployed and registered or None if the
|
129
|
+
stack was not found.
|
130
|
+
"""
|
@@ -0,0 +1,40 @@
|
|
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
|
+
"""Functionality to deploy a ZenML stack to a cloud provider."""
|
15
|
+
|
16
|
+
from typing import Type
|
17
|
+
|
18
|
+
from zenml.enums import StackDeploymentProvider
|
19
|
+
from zenml.stack_deployments.aws_stack_deployment import (
|
20
|
+
AWSZenMLCloudStackDeployment,
|
21
|
+
)
|
22
|
+
from zenml.stack_deployments.stack_deployment import ZenMLCloudStackDeployment
|
23
|
+
|
24
|
+
STACK_DEPLOYMENT_PROVIDERS = {
|
25
|
+
StackDeploymentProvider.AWS: AWSZenMLCloudStackDeployment,
|
26
|
+
}
|
27
|
+
|
28
|
+
|
29
|
+
def get_stack_deployment_class(
|
30
|
+
provider: StackDeploymentProvider,
|
31
|
+
) -> Type[ZenMLCloudStackDeployment]:
|
32
|
+
"""Get the ZenML Cloud Stack Deployment class for the specified provider.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
provider: The stack deployment provider.
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
The ZenML Cloud Stack Deployment class for the specified provider.
|
39
|
+
"""
|
40
|
+
return STACK_DEPLOYMENT_PROVIDERS[provider]
|
zenml/utils/function_utils.py
CHANGED
@@ -146,7 +146,7 @@ def _cli_wrapped_function(func: F) -> F:
|
|
146
146
|
if _is_valid_optional_arg(arg_type):
|
147
147
|
arg_type = arg_type.__args__[0]
|
148
148
|
arg_name = _cli_arg_name(arg_name)
|
149
|
-
if arg_type
|
149
|
+
if arg_type is bool:
|
150
150
|
options.append(
|
151
151
|
click.option(
|
152
152
|
f"--{arg_name}",
|
zenml/utils/pagination_utils.py
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Pagination utilities."""
|
15
15
|
|
16
|
-
from typing import Callable, List, TypeVar
|
16
|
+
from typing import Any, Callable, List, TypeVar
|
17
17
|
|
18
18
|
from zenml.models import BaseIdentifiedResponse, Page
|
19
19
|
|
@@ -21,20 +21,22 @@ AnyResponse = TypeVar("AnyResponse", bound=BaseIdentifiedResponse) # type: igno
|
|
21
21
|
|
22
22
|
|
23
23
|
def depaginate(
|
24
|
-
list_method: Callable[..., Page[AnyResponse]],
|
24
|
+
list_method: Callable[..., Page[AnyResponse]], **kwargs: Any
|
25
25
|
) -> List[AnyResponse]:
|
26
26
|
"""Depaginate the results from a client or store method that returns pages.
|
27
27
|
|
28
28
|
Args:
|
29
|
-
list_method: The list method to
|
29
|
+
list_method: The list method to depaginate.
|
30
|
+
**kwargs: Arguments for the list method.
|
30
31
|
|
31
32
|
Returns:
|
32
33
|
A list of the corresponding Response Models.
|
33
34
|
"""
|
34
|
-
page = list_method()
|
35
|
+
page = list_method(**kwargs)
|
35
36
|
items = list(page.items)
|
36
37
|
while page.index < page.total_pages:
|
37
|
-
page =
|
38
|
+
kwargs["page"] = page.index + 1
|
39
|
+
page = list_method(**kwargs)
|
38
40
|
items += list(page.items)
|
39
41
|
|
40
42
|
return items
|