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.
Files changed (240) hide show
  1. README.md +2 -2
  2. RELEASE_NOTES.md +120 -0
  3. zenml/VERSION +1 -1
  4. zenml/__init__.py +0 -4
  5. zenml/actions/pipeline_run/pipeline_run_action.py +19 -17
  6. zenml/analytics/enums.py +4 -6
  7. zenml/cli/__init__.py +28 -76
  8. zenml/cli/base.py +2 -2
  9. zenml/cli/pipeline.py +54 -61
  10. zenml/cli/stack.py +6 -8
  11. zenml/cli/web_login.py +8 -0
  12. zenml/client.py +232 -103
  13. zenml/config/build_configuration.py +43 -17
  14. zenml/config/compiler.py +14 -22
  15. zenml/config/docker_settings.py +80 -57
  16. zenml/config/pipeline_run_configuration.py +3 -0
  17. zenml/config/server_config.py +3 -0
  18. zenml/config/source.py +60 -1
  19. zenml/constants.py +11 -2
  20. zenml/entrypoints/base_entrypoint_configuration.py +53 -8
  21. zenml/enums.py +4 -1
  22. zenml/environment.py +25 -9
  23. zenml/image_builders/base_image_builder.py +1 -1
  24. zenml/image_builders/build_context.py +25 -72
  25. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +13 -4
  26. zenml/integrations/azure/__init__.py +4 -0
  27. zenml/integrations/azure/flavors/__init__.py +11 -0
  28. zenml/integrations/azure/flavors/azureml_orchestrator_flavor.py +263 -0
  29. zenml/{_hub → integrations/azure/orchestrators}/__init__.py +7 -2
  30. zenml/integrations/azure/orchestrators/azureml_orchestrator.py +544 -0
  31. zenml/integrations/azure/orchestrators/azureml_orchestrator_entrypoint_config.py +86 -0
  32. zenml/integrations/azure/step_operators/azureml_step_operator.py +3 -0
  33. zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +20 -2
  34. zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +19 -13
  35. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +7 -2
  36. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +123 -6
  37. zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +1 -1
  38. zenml/integrations/mlflow/__init__.py +1 -1
  39. zenml/integrations/mlflow/experiment_trackers/mlflow_experiment_tracker.py +3 -1
  40. zenml/integrations/mlflow/flavors/mlflow_experiment_tracker_flavor.py +3 -0
  41. zenml/logger.py +13 -0
  42. zenml/models/__init__.py +26 -22
  43. zenml/models/v2/base/filter.py +32 -0
  44. zenml/models/v2/core/pipeline.py +73 -89
  45. zenml/models/v2/core/pipeline_build.py +15 -11
  46. zenml/models/v2/core/pipeline_deployment.py +72 -24
  47. zenml/models/v2/core/pipeline_run.py +65 -1
  48. zenml/models/v2/core/run_template.py +393 -0
  49. zenml/models/v2/core/server_settings.py +12 -0
  50. zenml/models/v2/core/user.py +0 -21
  51. zenml/models/v2/misc/server_models.py +7 -1
  52. zenml/models/v2/misc/stack_deployment.py +5 -0
  53. zenml/models/v2/misc/user_auth.py +0 -7
  54. zenml/new/pipelines/build_utils.py +220 -89
  55. zenml/new/pipelines/code_archive.py +157 -0
  56. zenml/new/pipelines/pipeline.py +46 -78
  57. zenml/new/pipelines/run_utils.py +79 -1
  58. zenml/post_execution/pipeline.py +1 -4
  59. zenml/service_connectors/service_connector_utils.py +18 -2
  60. zenml/stack_deployments/aws_stack_deployment.py +32 -8
  61. zenml/stack_deployments/azure_stack_deployment.py +122 -10
  62. zenml/stack_deployments/gcp_stack_deployment.py +36 -7
  63. zenml/stack_deployments/stack_deployment.py +23 -7
  64. zenml/steps/base_step.py +3 -0
  65. zenml/steps/utils.py +0 -4
  66. zenml/utils/archivable.py +149 -0
  67. zenml/utils/code_utils.py +244 -0
  68. zenml/utils/notebook_utils.py +122 -0
  69. zenml/utils/package_utils.py +39 -0
  70. zenml/utils/pipeline_docker_image_builder.py +3 -96
  71. zenml/utils/source_utils.py +109 -1
  72. zenml/zen_server/dashboard/assets/{404-B_YdvmwS.js → 404-CRAA_Lew.js} +1 -1
  73. zenml/zen_server/dashboard/assets/@radix-BXWm7HOa.js +85 -0
  74. zenml/zen_server/dashboard/assets/{@react-router-CO-OsFwI.js → @react-router-l3lMcXA2.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{@reactflow-l_1hUr1S.js → @reactflow-CeVxyqYT.js} +2 -2
  76. zenml/zen_server/dashboard/assets/{@tanstack-DYiOyJUL.js → @tanstack-FmcYZMuX.js} +4 -4
  77. zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-ErO9aOgK.js +1 -0
  78. zenml/zen_server/dashboard/assets/{AwarenessChannel-CFg5iX4Z.js → AwarenessChannel-CLXo5rKM.js} +1 -1
  79. zenml/zen_server/dashboard/assets/{CodeSnippet-Dvkx_82E.js → CodeSnippet-D0VLxT2A.js} +2 -2
  80. zenml/zen_server/dashboard/assets/CollapsibleCard-BaUPiVg0.js +1 -0
  81. zenml/zen_server/dashboard/assets/{Commands-DoN1xrEq.js → Commands-JrcZK-3j.js} +1 -1
  82. zenml/zen_server/dashboard/assets/CopyButton-Dbo52T1K.js +2 -0
  83. zenml/zen_server/dashboard/assets/{CsvVizualization-Ck-nZ43m.js → CsvVizualization-D3kAypDj.js} +3 -3
  84. zenml/zen_server/dashboard/assets/DisplayDate-DizbSeT-.js +1 -0
  85. zenml/zen_server/dashboard/assets/EditSecretDialog-Bd7mFLS4.js +1 -0
  86. zenml/zen_server/dashboard/assets/{EmptyState-BMLnFVlB.js → EmptyState-BHblM39I.js} +1 -1
  87. zenml/zen_server/dashboard/assets/{Error-kLtljEOM.js → Error-C6LeJSER.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{ExecutionStatus-DguLLgTK.js → ExecutionStatus-jH4OrWBq.js} +1 -1
  89. zenml/zen_server/dashboard/assets/{Helpbox-BXUMP21n.js → Helpbox-aAB2XP-z.js} +1 -1
  90. zenml/zen_server/dashboard/assets/{Infobox-DSt0O-dm.js → Infobox-BQ0aty32.js} +1 -1
  91. zenml/zen_server/dashboard/assets/{InlineAvatar-xsrsIGE-.js → InlineAvatar-DpTLgM3Q.js} +1 -1
  92. zenml/zen_server/dashboard/assets/Lock-CNyJvf2r.js +1 -0
  93. zenml/zen_server/dashboard/assets/{MarkdownVisualization-xp3hhULl.js → MarkdownVisualization-Bajxn0HY.js} +1 -1
  94. zenml/zen_server/dashboard/assets/NumberBox-BmKE0qnO.js +1 -0
  95. zenml/zen_server/dashboard/assets/{PasswordChecker-DUveqlva.js → PasswordChecker-yGGoJSB-.js} +1 -1
  96. zenml/zen_server/dashboard/assets/ProviderRadio-BBqkIuTd.js +1 -0
  97. zenml/zen_server/dashboard/assets/RadioItem-xLhXoiFV.js +1 -0
  98. zenml/zen_server/dashboard/assets/SearchField-C9R0mdaX.js +1 -0
  99. zenml/zen_server/dashboard/assets/{SetPassword-BXGTWiwj.js → SetPassword-52sNxNiO.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{SuccessStep-DZC60t0x.js → SuccessStep-DlkItqYG.js} +1 -1
  101. zenml/zen_server/dashboard/assets/Tick-uxv80Q6a.js +1 -0
  102. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DGvwFWO1.js → UpdatePasswordSchemas-oN4G3sKz.js} +1 -1
  103. zenml/zen_server/dashboard/assets/{aws-BgKTfTfx.js → aws-0_3UsPif.js} +1 -1
  104. zenml/zen_server/dashboard/assets/{check-circle-i56092KI.js → check-circle-1_I207rW.js} +1 -1
  105. zenml/zen_server/dashboard/assets/chevron-down-BpaF8JqM.js +1 -0
  106. zenml/zen_server/dashboard/assets/{chevron-right-double-CZBOf6JM.js → chevron-right-double-Dk8e2L99.js} +1 -1
  107. zenml/zen_server/dashboard/assets/{cloud-only-C_yFCAkP.js → cloud-only-BkUuI0lZ.js} +1 -1
  108. zenml/zen_server/dashboard/assets/components-Br2ezRib.js +1 -0
  109. zenml/zen_server/dashboard/assets/{copy-BXNk6BjL.js → copy-f3XGPPxt.js} +1 -1
  110. zenml/zen_server/dashboard/assets/{database-1xWSgZfO.js → database-cXYNX9tt.js} +1 -1
  111. zenml/zen_server/dashboard/assets/{docker-CQMVm_4d.js → docker-8uj__HHK.js} +1 -1
  112. zenml/zen_server/dashboard/assets/dots-horizontal-sKQlWEni.js +1 -0
  113. zenml/zen_server/dashboard/assets/edit-C0MVvPD2.js +1 -0
  114. zenml/zen_server/dashboard/assets/{file-text-CqD_iu6l.js → file-text-B9JibxTs.js} +1 -1
  115. zenml/zen_server/dashboard/assets/{help-bu_DgLKI.js → help-FuHlZwn0.js} +1 -1
  116. zenml/zen_server/dashboard/assets/{index-rK_Wuy2W.js → index-Bd1xgUQG.js} +1 -1
  117. zenml/zen_server/dashboard/assets/index-DaGknux4.css +1 -0
  118. zenml/zen_server/dashboard/assets/{index-BczVOqUf.js → index-DhIZtpxB.js} +5 -5
  119. zenml/zen_server/dashboard/assets/index.esm-DT4uyn2i.js +1 -0
  120. zenml/zen_server/dashboard/assets/layout-D6oiSbfd.js +1 -0
  121. zenml/zen_server/dashboard/assets/{login-mutation-CrHrndTI.js → login-mutation-13A_JSVA.js} +1 -1
  122. zenml/zen_server/dashboard/assets/{logs-D8k8BVFf.js → logs-CgeE2vZP.js} +1 -1
  123. zenml/zen_server/dashboard/assets/{not-found-DYa4pC-C.js → not-found-B0Mmb90p.js} +1 -1
  124. zenml/zen_server/dashboard/assets/package-DdkziX79.js +1 -0
  125. zenml/zen_server/dashboard/assets/page-7-v2OBm-.js +1 -0
  126. zenml/zen_server/dashboard/assets/{page-MFQyIJd3.js → page-B3ozwdD1.js} +1 -1
  127. zenml/zen_server/dashboard/assets/{page-BkuQDIf-.js → page-BGwA9B1M.js} +1 -1
  128. zenml/zen_server/dashboard/assets/{page-1iL8aMqs.js → page-BkjAUyTA.js} +1 -1
  129. zenml/zen_server/dashboard/assets/page-BnacgBiy.js +1 -0
  130. zenml/zen_server/dashboard/assets/page-BxF_KMQ3.js +2 -0
  131. zenml/zen_server/dashboard/assets/page-C4POHC0K.js +1 -0
  132. zenml/zen_server/dashboard/assets/page-C9kudd44.js +9 -0
  133. zenml/zen_server/dashboard/assets/page-CA1j3GpJ.js +1 -0
  134. zenml/zen_server/dashboard/assets/page-CCY6yfmu.js +1 -0
  135. zenml/zen_server/dashboard/assets/page-CgTe7Bme.js +1 -0
  136. zenml/zen_server/dashboard/assets/{page-8a4UMKXZ.js → page-Cgn-6v2Y.js} +1 -1
  137. zenml/zen_server/dashboard/assets/page-CxQmQqDw.js +1 -0
  138. zenml/zen_server/dashboard/assets/page-D2Goey3H.js +1 -0
  139. zenml/zen_server/dashboard/assets/page-DLpOnf7u.js +1 -0
  140. zenml/zen_server/dashboard/assets/{page-BhgCDInH.js → page-DSTQnBk-.js} +1 -1
  141. zenml/zen_server/dashboard/assets/{page-1h_sD1jz.js → page-DTysUGOy.js} +1 -1
  142. zenml/zen_server/dashboard/assets/{page-2grKx_MY.js → page-D_EXUFJb.js} +1 -1
  143. zenml/zen_server/dashboard/assets/page-Db15QzsM.js +1 -0
  144. zenml/zen_server/dashboard/assets/{page-BDns21Iz.js → page-DugsjcQ_.js} +1 -1
  145. zenml/zen_server/dashboard/assets/{page-C6-UGEbH.js → page-OFKSPyN7.js} +1 -1
  146. zenml/zen_server/dashboard/assets/{page-BkeAAYwp.js → page-RnG-qhv9.js} +1 -1
  147. zenml/zen_server/dashboard/assets/{page-CCNRIt_f.js → page-T2BtjwPl.js} +1 -1
  148. zenml/zen_server/dashboard/assets/page-TXe1Eo3Z.js +1 -0
  149. zenml/zen_server/dashboard/assets/{page-BnaevhnB.js → page-YiF_fNbe.js} +1 -1
  150. zenml/zen_server/dashboard/assets/{page-uA5prJGY.js → page-hQaiQXfg.js} +1 -1
  151. zenml/zen_server/dashboard/assets/persist-3-5nOJ6m.js +1 -0
  152. zenml/zen_server/dashboard/assets/{play-circle-CNtZKDnW.js → play-circle-XSkLR12B.js} +1 -1
  153. zenml/zen_server/dashboard/assets/plus-FB9-lEq_.js +1 -0
  154. zenml/zen_server/dashboard/assets/refresh-COb6KYDi.js +1 -0
  155. zenml/zen_server/dashboard/assets/sharedSchema-BoYx_B_L.js +14 -0
  156. zenml/zen_server/dashboard/assets/{stack-detail-query-Cficsl6d.js → stack-detail-query-B-US_-wa.js} +1 -1
  157. zenml/zen_server/dashboard/assets/{terminal-By9cErXc.js → terminal-grtjrIEJ.js} +1 -1
  158. zenml/zen_server/dashboard/assets/trash-Cd5CSFqA.js +1 -0
  159. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-7d8xi1tS.js → update-server-settings-mutation-B8GB_ubU.js} +1 -1
  160. zenml/zen_server/dashboard/assets/{url-D7mAQGUM.js → url-hcMJkz8p.js} +1 -1
  161. zenml/zen_server/dashboard/assets/{zod-BhoGpZ63.js → zod-CnykDKJj.js} +1 -1
  162. zenml/zen_server/dashboard/index.html +7 -7
  163. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  164. zenml/zen_server/dashboard_legacy/index.html +1 -1
  165. zenml/zen_server/dashboard_legacy/{precache-manifest.12246c7548e71e2c4438e496360de80c.js → precache-manifest.9c473c96a43298343a7ce1256183123b.js} +4 -4
  166. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  167. zenml/zen_server/dashboard_legacy/static/js/{main.3b27024b.chunk.js → main.463c90b9.chunk.js} +2 -2
  168. zenml/zen_server/dashboard_legacy/static/js/{main.3b27024b.chunk.js.map → main.463c90b9.chunk.js.map} +1 -1
  169. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  170. zenml/zen_server/deploy/helm/README.md +2 -2
  171. zenml/zen_server/rbac/models.py +1 -0
  172. zenml/zen_server/rbac/utils.py +4 -0
  173. zenml/zen_server/routers/pipeline_builds_endpoints.py +2 -66
  174. zenml/zen_server/routers/pipeline_deployments_endpoints.py +2 -53
  175. zenml/zen_server/routers/pipelines_endpoints.py +1 -74
  176. zenml/zen_server/routers/run_templates_endpoints.py +212 -0
  177. zenml/zen_server/routers/stack_deployment_endpoints.py +6 -0
  178. zenml/zen_server/routers/users_endpoints.py +0 -7
  179. zenml/zen_server/routers/workspaces_endpoints.py +79 -0
  180. zenml/zen_server/{pipeline_deployment → template_execution}/runner_entrypoint_configuration.py +1 -8
  181. zenml/zen_server/{pipeline_deployment → template_execution}/utils.py +214 -92
  182. zenml/zen_server/utils.py +77 -2
  183. zenml/zen_server/zen_server_api.py +54 -2
  184. zenml/zen_stores/base_zen_store.py +7 -1
  185. zenml/zen_stores/migrations/versions/0.63.0_release.py +23 -0
  186. zenml/zen_stores/migrations/versions/0.64.0_release.py +23 -0
  187. zenml/zen_stores/migrations/versions/026d4577b6a0_add_code_path.py +39 -0
  188. zenml/zen_stores/migrations/versions/3dcc5d20e82f_add_last_user_activity.py +51 -0
  189. zenml/zen_stores/migrations/versions/7d1919bb1ef0_add_run_templates.py +100 -0
  190. zenml/zen_stores/migrations/versions/909550c7c4da_remove_user_hub_token.py +36 -0
  191. zenml/zen_stores/migrations/versions/b59aa68fdb1f_simplify_pipelines.py +139 -0
  192. zenml/zen_stores/rest_zen_store.py +112 -39
  193. zenml/zen_stores/schemas/__init__.py +2 -0
  194. zenml/zen_stores/schemas/pipeline_build_schemas.py +3 -3
  195. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +32 -2
  196. zenml/zen_stores/schemas/pipeline_run_schemas.py +29 -3
  197. zenml/zen_stores/schemas/pipeline_schemas.py +29 -30
  198. zenml/zen_stores/schemas/run_template_schemas.py +264 -0
  199. zenml/zen_stores/schemas/server_settings_schemas.py +2 -0
  200. zenml/zen_stores/schemas/step_run_schemas.py +11 -4
  201. zenml/zen_stores/schemas/user_schemas.py +0 -2
  202. zenml/zen_stores/sql_zen_store.py +389 -151
  203. zenml/zen_stores/template_utils.py +261 -0
  204. zenml/zen_stores/zen_store_interface.py +93 -20
  205. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/METADATA +3 -3
  206. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/RECORD +211 -184
  207. zenml/_hub/client.py +0 -289
  208. zenml/_hub/constants.py +0 -21
  209. zenml/_hub/utils.py +0 -79
  210. zenml/cli/hub.py +0 -1116
  211. zenml/models/v2/core/pipeline_namespace.py +0 -113
  212. zenml/models/v2/misc/hub_plugin_models.py +0 -79
  213. zenml/new/pipelines/deserialization_utils.py +0 -292
  214. zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +0 -85
  215. zenml/zen_server/dashboard/assets/CollapsibleCard-opiuBHHc.js +0 -1
  216. zenml/zen_server/dashboard/assets/CopyButton-Cr7xYEPb.js +0 -2
  217. zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +0 -1
  218. zenml/zen_server/dashboard/assets/Pagination-C6X-mifw.js +0 -1
  219. zenml/zen_server/dashboard/assets/index-EpMIKgrI.css +0 -1
  220. zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +0 -1
  221. zenml/zen_server/dashboard/assets/package-B3fWP-Dh.js +0 -1
  222. zenml/zen_server/dashboard/assets/page-5NCOHOsy.js +0 -1
  223. zenml/zen_server/dashboard/assets/page-B6h3iaHJ.js +0 -1
  224. zenml/zen_server/dashboard/assets/page-Bi-wtWiO.js +0 -5
  225. zenml/zen_server/dashboard/assets/page-Bq0YxkLV.js +0 -1
  226. zenml/zen_server/dashboard/assets/page-Bs2F4eoD.js +0 -2
  227. zenml/zen_server/dashboard/assets/page-CHNxpz3n.js +0 -1
  228. zenml/zen_server/dashboard/assets/page-DgorQFqi.js +0 -1
  229. zenml/zen_server/dashboard/assets/page-K8ebxVIs.js +0 -1
  230. zenml/zen_server/dashboard/assets/page-TgCF0P_U.js +0 -1
  231. zenml/zen_server/dashboard/assets/page-ZnCEe-eK.js +0 -9
  232. zenml/zen_server/dashboard/assets/persist-D7HJNBWx.js +0 -1
  233. zenml/zen_server/dashboard/assets/plus-C8WOyCzt.js +0 -1
  234. zenml/zen_server/dashboard/assets/secrets-video-OBJ6irhH.svg +0 -21
  235. zenml/zen_server/dashboard/assets/stacks-video-7gfxpAq4.svg +0 -21
  236. /zenml/zen_server/{pipeline_deployment → template_execution}/__init__.py +0 -0
  237. /zenml/zen_server/{pipeline_deployment → template_execution}/workload_manager_interface.py +0 -0
  238. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/LICENSE +0 -0
  239. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/WHEEL +0 -0
  240. {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
- # TODO: Implement this
41
- return ""
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
- # TODO: Implement this
55
- return ""
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
- # TODO: Implement this
68
- return ""
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
- # TODO: Implement this
89
- return {}
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 ZenMLCloudStackDeployment
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 the
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, or YAML configuration snippet etc.).
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 specified cloud
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
- config = f"""
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 the
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, or YAML configuration snippet etc.).
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 specified cloud
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, date_start: Optional[datetime.datetime] = None
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.deployment:
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()