zenml-nightly 0.58.2.dev20240626__py3-none-any.whl → 0.61.0.dev20240712__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. README.md +30 -9
  2. RELEASE_NOTES.md +240 -0
  3. zenml/VERSION +1 -1
  4. zenml/analytics/enums.py +3 -0
  5. zenml/cli/__init__.py +28 -0
  6. zenml/cli/artifact.py +1 -2
  7. zenml/cli/integration.py +9 -8
  8. zenml/cli/server.py +6 -0
  9. zenml/cli/stack.py +946 -39
  10. zenml/cli/stack_components.py +7 -0
  11. zenml/cli/text_utils.py +35 -1
  12. zenml/cli/utils.py +127 -10
  13. zenml/client.py +23 -14
  14. zenml/config/docker_settings.py +8 -5
  15. zenml/constants.py +10 -1
  16. zenml/container_registries/base_container_registry.py +1 -0
  17. zenml/enums.py +7 -0
  18. zenml/event_hub/event_hub.py +5 -8
  19. zenml/integrations/aws/__init__.py +1 -0
  20. zenml/integrations/azure/__init__.py +1 -0
  21. zenml/integrations/deepchecks/__init__.py +1 -0
  22. zenml/integrations/discord/__init__.py +1 -0
  23. zenml/integrations/evidently/__init__.py +1 -0
  24. zenml/integrations/facets/__init__.py +1 -0
  25. zenml/integrations/feast/__init__.py +1 -0
  26. zenml/integrations/gcp/__init__.py +3 -1
  27. zenml/integrations/gcp/google_credentials_mixin.py +1 -1
  28. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +320 -64
  29. zenml/integrations/huggingface/__init__.py +1 -0
  30. zenml/integrations/integration.py +24 -0
  31. zenml/integrations/kubeflow/__init__.py +3 -0
  32. zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +1 -1
  33. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +0 -1
  34. zenml/integrations/kubernetes/__init__.py +3 -1
  35. zenml/integrations/kubernetes/orchestrators/kube_utils.py +4 -1
  36. zenml/integrations/label_studio/annotators/label_studio_annotator.py +1 -0
  37. zenml/integrations/langchain/__init__.py +1 -0
  38. zenml/integrations/mlflow/__init__.py +3 -1
  39. zenml/integrations/neural_prophet/__init__.py +1 -0
  40. zenml/integrations/polars/__init__.py +1 -0
  41. zenml/integrations/prodigy/__init__.py +1 -0
  42. zenml/integrations/pycaret/__init__.py +6 -0
  43. zenml/integrations/registry.py +37 -0
  44. zenml/integrations/s3/artifact_stores/s3_artifact_store.py +17 -6
  45. zenml/integrations/seldon/__init__.py +1 -0
  46. zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -0
  47. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +2 -2
  48. zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +1 -1
  49. zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py +2 -2
  50. zenml/integrations/skypilot_aws/__init__.py +2 -1
  51. zenml/integrations/skypilot_azure/__init__.py +1 -1
  52. zenml/integrations/skypilot_gcp/__init__.py +1 -1
  53. zenml/integrations/skypilot_lambda/__init__.py +1 -1
  54. zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +1 -1
  55. zenml/integrations/slack/__init__.py +1 -0
  56. zenml/integrations/tekton/__init__.py +1 -0
  57. zenml/integrations/tensorboard/__init__.py +0 -1
  58. zenml/integrations/tensorflow/__init__.py +18 -6
  59. zenml/integrations/wandb/__init__.py +1 -0
  60. zenml/models/__init__.py +11 -0
  61. zenml/models/v2/core/component.py +18 -0
  62. zenml/models/v2/core/model.py +1 -2
  63. zenml/models/v2/core/service_connector.py +17 -0
  64. zenml/models/v2/core/stack.py +31 -0
  65. zenml/models/v2/misc/full_stack.py +97 -0
  66. zenml/models/v2/misc/stack_deployment.py +86 -0
  67. zenml/new/pipelines/pipeline.py +1 -1
  68. zenml/orchestrators/input_utils.py +3 -6
  69. zenml/stack/stack.py +3 -6
  70. zenml/stack_deployments/__init__.py +14 -0
  71. zenml/stack_deployments/aws_stack_deployment.py +254 -0
  72. zenml/stack_deployments/gcp_stack_deployment.py +260 -0
  73. zenml/stack_deployments/stack_deployment.py +208 -0
  74. zenml/stack_deployments/utils.py +44 -0
  75. zenml/utils/function_utils.py +1 -1
  76. zenml/utils/pagination_utils.py +7 -5
  77. zenml/utils/pipeline_docker_image_builder.py +97 -68
  78. zenml/utils/pydantic_utils.py +6 -5
  79. zenml/zen_server/cloud_utils.py +18 -3
  80. zenml/zen_server/dashboard/assets/{404-CDPQCl4D.js → 404-DpJaNHKF.js} +1 -1
  81. zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +85 -0
  82. zenml/zen_server/dashboard/assets/{@react-router-DYovave8.js → @react-router-CO-OsFwI.js} +2 -2
  83. zenml/zen_server/dashboard/assets/{@reactflow-CHBapDaj.js → @reactflow-DJfzkHO1.js} +2 -2
  84. zenml/zen_server/dashboard/assets/@tanstack-DYiOyJUL.js +22 -0
  85. zenml/zen_server/dashboard/assets/AwarenessChannel-BYDLT2xC.js +1 -0
  86. zenml/zen_server/dashboard/assets/{CodeSnippet-BidtnWOi.js → CodeSnippet-BkOuRmyq.js} +2 -2
  87. zenml/zen_server/dashboard/assets/Commands-ZvWR1BRs.js +1 -0
  88. zenml/zen_server/dashboard/assets/CopyButton-DVwLkafa.js +2 -0
  89. zenml/zen_server/dashboard/assets/{CsvVizualization-BOuez-fG.js → CsvVizualization-C2IiqX4I.js} +7 -7
  90. zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +1 -0
  91. zenml/zen_server/dashboard/assets/EmptyState-BMLnFVlB.js +1 -0
  92. zenml/zen_server/dashboard/assets/Error-CqX0VqW_.js +1 -0
  93. zenml/zen_server/dashboard/assets/ExecutionStatus-BoLUXR9t.js +1 -0
  94. zenml/zen_server/dashboard/assets/Helpbox-LFydyVwh.js +1 -0
  95. zenml/zen_server/dashboard/assets/Infobox-DnENC0sh.js +1 -0
  96. zenml/zen_server/dashboard/assets/InlineAvatar-CbJtYr0t.js +1 -0
  97. zenml/zen_server/dashboard/assets/{MarkdownVisualization-DsB2QZiK.js → MarkdownVisualization-xp3hhULl.js} +2 -2
  98. zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +1 -0
  99. zenml/zen_server/dashboard/assets/PasswordChecker-DUveqlva.js +1 -0
  100. zenml/zen_server/dashboard/assets/SetPassword-BYBdbQDo.js +1 -0
  101. zenml/zen_server/dashboard/assets/SuccessStep-Nx743hll.js +1 -0
  102. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DnM-c11H.js → UpdatePasswordSchemas-DF9gSzE0.js} +1 -1
  103. zenml/zen_server/dashboard/assets/{aws-t0gKCj_R.js → aws-BgKTfTfx.js} +1 -1
  104. zenml/zen_server/dashboard/assets/{check-circle-BVvhm5dy.js → check-circle-i56092KI.js} +1 -1
  105. zenml/zen_server/dashboard/assets/{chevron-down-zcvCWmyP.js → chevron-down-D_ZlKMqH.js} +1 -1
  106. zenml/zen_server/dashboard/assets/{chevron-right-double-CJ50E9Gr.js → chevron-right-double-BiEMg7rd.js} +1 -1
  107. zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +1 -0
  108. zenml/zen_server/dashboard/assets/{copy-BRhQz3j-.js → copy-BXNk6BjL.js} +1 -1
  109. zenml/zen_server/dashboard/assets/{database-CRRnyFWh.js → database-1xWSgZfO.js} +1 -1
  110. zenml/zen_server/dashboard/assets/{docker-BAonhm6G.js → docker-CQMVm_4d.js} +1 -1
  111. zenml/zen_server/dashboard/assets/{file-text-CbVERUON.js → file-text-CqD_iu6l.js} +1 -1
  112. zenml/zen_server/dashboard/assets/{help-B8rqCvqn.js → help-bu_DgLKI.js} +1 -1
  113. zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +1 -0
  114. zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +55 -0
  115. zenml/zen_server/dashboard/assets/index-inApY3KQ.css +1 -0
  116. zenml/zen_server/dashboard/assets/index-rK_Wuy2W.js +1 -0
  117. zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +1 -0
  118. zenml/zen_server/dashboard/assets/{login-mutation-wzzl23C6.js → login-mutation-BUnVASxp.js} +1 -1
  119. zenml/zen_server/dashboard/assets/not-found-B4VnX8gK.js +1 -0
  120. zenml/zen_server/dashboard/assets/package-CsUhPmou.js +1 -0
  121. zenml/zen_server/dashboard/assets/{page-BmkSiYeQ.js → page-3efNCDeb.js} +2 -2
  122. zenml/zen_server/dashboard/assets/page-7zTHbhhI.js +1 -0
  123. zenml/zen_server/dashboard/assets/page-BEs6jK71.js +1 -0
  124. zenml/zen_server/dashboard/assets/page-BpSqIf4B.js +1 -0
  125. zenml/zen_server/dashboard/assets/{page-AQKopn_4.js → page-Bx6o0ARS.js} +1 -1
  126. zenml/zen_server/dashboard/assets/page-C43QGHTt.js +9 -0
  127. zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +1 -0
  128. zenml/zen_server/dashboard/assets/page-CRTJ0UuR.js +1 -0
  129. zenml/zen_server/dashboard/assets/page-CUZIGO-3.js +1 -0
  130. zenml/zen_server/dashboard/assets/page-CaopxiU1.js +1 -0
  131. zenml/zen_server/dashboard/assets/{page-CuT1SUik.js → page-Cx67M0QT.js} +1 -1
  132. zenml/zen_server/dashboard/assets/page-D7Z399xy.js +1 -0
  133. zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +1 -0
  134. zenml/zen_server/dashboard/assets/{page-BzVZGExK.js → page-DKlIdAe5.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{page-Bi5AI0S7.js → page-DMOYZppS.js} +1 -1
  136. zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +2 -0
  137. zenml/zen_server/dashboard/assets/{page-BW6Ket3a.js → page-Dc_7KMQE.js} +1 -1
  138. zenml/zen_server/dashboard/assets/page-DvCvroOM.js +1 -0
  139. zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +1 -0
  140. zenml/zen_server/dashboard/assets/page-JyfeDUfu.js +1 -0
  141. zenml/zen_server/dashboard/assets/{page-yN4rZ-ZS.js → page-Sxn82W-5.js} +1 -1
  142. zenml/zen_server/dashboard/assets/page-TKXERe16.js +1 -0
  143. zenml/zen_server/dashboard/assets/page-Xu8JEjSU.js +1 -0
  144. zenml/zen_server/dashboard/assets/{play-circle-DK5QMJyp.js → play-circle-CNtZKDnW.js} +1 -1
  145. zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +1 -0
  146. zenml/zen_server/dashboard/assets/{terminal-B2ovgWuz.js → terminal-By9cErXc.js} +1 -1
  147. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-0Wgz8pUE.js → update-server-settings-mutation-CR8e3Sir.js} +1 -1
  148. zenml/zen_server/dashboard/assets/{url-6_xv0WJS.js → url-DuQMeqYA.js} +1 -1
  149. zenml/zen_server/dashboard/assets/{zod-DrZvVLjd.js → zod-BhoGpZ63.js} +1 -1
  150. zenml/zen_server/dashboard/index.html +7 -7
  151. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  152. zenml/zen_server/dashboard_legacy/index.html +1 -1
  153. zenml/zen_server/dashboard_legacy/{precache-manifest.f4abc5b7cfa7d90c1caf5521918e29a8.js → precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js} +4 -4
  154. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  155. zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js → main.382439a7.chunk.js} +2 -2
  156. zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js.map → main.382439a7.chunk.js.map} +1 -1
  157. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  158. zenml/zen_server/deploy/helm/README.md +2 -2
  159. zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +11 -5
  160. zenml/zen_server/pipeline_deployment/utils.py +57 -44
  161. zenml/zen_server/rbac/zenml_cloud_rbac.py +11 -5
  162. zenml/zen_server/routers/stack_deployment_endpoints.py +158 -0
  163. zenml/zen_server/routers/workspaces_endpoints.py +64 -0
  164. zenml/zen_server/zen_server_api.py +2 -0
  165. zenml/zen_stores/migrations/utils.py +1 -1
  166. zenml/zen_stores/migrations/versions/0.60.0_release.py +23 -0
  167. zenml/zen_stores/migrations/versions/0.61.0_release.py +23 -0
  168. zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
  169. zenml/zen_stores/rest_zen_store.py +145 -4
  170. zenml/zen_stores/schemas/stack_schemas.py +10 -0
  171. zenml/zen_stores/schemas/step_run_schemas.py +27 -11
  172. zenml/zen_stores/sql_zen_store.py +300 -6
  173. zenml/zen_stores/zen_store_interface.py +80 -0
  174. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/METADATA +32 -10
  175. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/RECORD +178 -162
  176. zenml/zen_server/dashboard/assets/@radix-C9DBgJhe.js +0 -77
  177. zenml/zen_server/dashboard/assets/@tanstack-CEbkxrhX.js +0 -30
  178. zenml/zen_server/dashboard/assets/AwarenessChannel-nXGpmj_f.js +0 -1
  179. zenml/zen_server/dashboard/assets/Cards-nwsvQLVS.js +0 -1
  180. zenml/zen_server/dashboard/assets/Commands-DuIWKg_Q.js +0 -1
  181. zenml/zen_server/dashboard/assets/CopyButton-B_YSm-Ds.js +0 -2
  182. zenml/zen_server/dashboard/assets/DisplayDate-BdguISQF.js +0 -1
  183. zenml/zen_server/dashboard/assets/EmptyState-BkooiGtL.js +0 -1
  184. zenml/zen_server/dashboard/assets/Error-B6M0dPph.js +0 -1
  185. zenml/zen_server/dashboard/assets/Helpbox-BQoqCm04.js +0 -1
  186. zenml/zen_server/dashboard/assets/Infobox-Ce9mefqU.js +0 -1
  187. zenml/zen_server/dashboard/assets/InlineAvatar-DGf3dVhV.js +0 -1
  188. zenml/zen_server/dashboard/assets/PageHeader-DGaemzjc.js +0 -1
  189. zenml/zen_server/dashboard/assets/Pagination-DVYfBCCc.js +0 -1
  190. zenml/zen_server/dashboard/assets/PasswordChecker-DSLBp7Vl.js +0 -1
  191. zenml/zen_server/dashboard/assets/SetPassword-B5s7DJug.js +0 -1
  192. zenml/zen_server/dashboard/assets/SuccessStep-ZzczaM7g.js +0 -1
  193. zenml/zen_server/dashboard/assets/cloud-only-Ba_ShBR5.js +0 -1
  194. zenml/zen_server/dashboard/assets/index-CWJ3xbIf.css +0 -1
  195. zenml/zen_server/dashboard/assets/index-QORVVTMN.js +0 -55
  196. zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +0 -1
  197. zenml/zen_server/dashboard/assets/not-found-Dh2la7kh.js +0 -1
  198. zenml/zen_server/dashboard/assets/page-B-5jAKoO.js +0 -1
  199. zenml/zen_server/dashboard/assets/page-B-vWk8a6.js +0 -1
  200. zenml/zen_server/dashboard/assets/page-B0BrqfS8.js +0 -1
  201. zenml/zen_server/dashboard/assets/page-BQxVFlUl.js +0 -1
  202. zenml/zen_server/dashboard/assets/page-ByrHy6Ss.js +0 -1
  203. zenml/zen_server/dashboard/assets/page-CPtY4Kv_.js +0 -1
  204. zenml/zen_server/dashboard/assets/page-CmmukLsl.js +0 -1
  205. zenml/zen_server/dashboard/assets/page-D2D-7qyr.js +0 -9
  206. zenml/zen_server/dashboard/assets/page-DAQQyLxT.js +0 -1
  207. zenml/zen_server/dashboard/assets/page-DHkUMl_E.js +0 -1
  208. zenml/zen_server/dashboard/assets/page-DZCbwOEs.js +0 -2
  209. zenml/zen_server/dashboard/assets/page-DdaIt20-.js +0 -1
  210. zenml/zen_server/dashboard/assets/page-LqLs24Ot.js +0 -1
  211. zenml/zen_server/dashboard/assets/page-lebv0c7C.js +0 -1
  212. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/LICENSE +0 -0
  213. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/WHEEL +0 -0
  214. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/entry_points.txt +0 -0
@@ -111,6 +111,7 @@ from zenml.enums import (
111
111
  SecretsStoreType,
112
112
  SorterOps,
113
113
  StackComponentType,
114
+ StackDeploymentProvider,
114
115
  StepRunInputArtifactType,
115
116
  StepRunOutputArtifactType,
116
117
  StoreType,
@@ -164,6 +165,7 @@ from zenml.models import (
164
165
  ComponentRequest,
165
166
  ComponentResponse,
166
167
  ComponentUpdate,
168
+ DeployedStack,
167
169
  EventSourceFilter,
168
170
  EventSourceRequest,
169
171
  EventSourceResponse,
@@ -172,6 +174,7 @@ from zenml.models import (
172
174
  FlavorRequest,
173
175
  FlavorResponse,
174
176
  FlavorUpdate,
177
+ FullStackRequest,
175
178
  LogsResponse,
176
179
  ModelFilter,
177
180
  ModelRequest,
@@ -242,6 +245,8 @@ from zenml.models import (
242
245
  ServiceRequest,
243
246
  ServiceResponse,
244
247
  ServiceUpdate,
248
+ StackDeploymentConfig,
249
+ StackDeploymentInfo,
245
250
  StackFilter,
246
251
  StackRequest,
247
252
  StackResponse,
@@ -1548,12 +1553,18 @@ class SqlZenStore(BaseZenStore):
1548
1553
  revisions_afterwards = self.alembic.current_revisions()
1549
1554
 
1550
1555
  if current_revisions != revisions_afterwards:
1551
- if current_revisions and version.parse(
1552
- current_revisions[0]
1553
- ) < version.parse("0.57.1"):
1554
- # We want to send the missing user enriched events for users
1555
- # which were created pre 0.57.1 and only on one upgrade
1556
- self._should_send_user_enriched_events = True
1556
+ try:
1557
+ if current_revisions and version.parse(
1558
+ current_revisions[0]
1559
+ ) < version.parse("0.57.1"):
1560
+ # We want to send the missing user enriched events for users
1561
+ # which were created pre 0.57.1 and only on one upgrade
1562
+ self._should_send_user_enriched_events = True
1563
+ except version.InvalidVersion:
1564
+ # This can happen if the database is not currently
1565
+ # stamped with an official ZenML version (e.g. in
1566
+ # development environments).
1567
+ pass
1557
1568
 
1558
1569
  self._sync_flavors()
1559
1570
 
@@ -6911,6 +6922,9 @@ class SqlZenStore(BaseZenStore):
6911
6922
  name=stack.name,
6912
6923
  description=stack.description,
6913
6924
  components=defined_components,
6925
+ labels=base64.b64encode(
6926
+ json.dumps(stack.labels).encode("utf-8")
6927
+ ),
6914
6928
  )
6915
6929
 
6916
6930
  session.add(new_stack_schema)
@@ -6919,6 +6933,223 @@ class SqlZenStore(BaseZenStore):
6919
6933
 
6920
6934
  return new_stack_schema.to_model(include_metadata=True)
6921
6935
 
6936
+ def create_full_stack(self, full_stack: FullStackRequest) -> StackResponse:
6937
+ """Register a full stack.
6938
+
6939
+ Args:
6940
+ full_stack: The full stack configuration.
6941
+
6942
+ Returns:
6943
+ The registered stack.
6944
+
6945
+ Raises:
6946
+ ValueError: If the full stack creation fails, due to the corrupted
6947
+ input.
6948
+ RuntimeError: If the full stack creation fails, due to unforeseen
6949
+ errors.
6950
+ """
6951
+ # For clean-up purposes, each created entity is tracked here
6952
+ service_connectors_created_ids: List[UUID] = []
6953
+ components_created_ids: List[UUID] = []
6954
+
6955
+ try:
6956
+ # Validate the name of the new stack
6957
+ validate_name(full_stack)
6958
+
6959
+ if full_stack.labels is None:
6960
+ full_stack.labels = {}
6961
+
6962
+ full_stack.labels.update({"zenml:full_stack": True})
6963
+
6964
+ # Service Connectors
6965
+ service_connectors: List[ServiceConnectorResponse] = []
6966
+
6967
+ for connector_id_or_info in full_stack.service_connectors:
6968
+ # Fetch an existing service connector
6969
+ if isinstance(connector_id_or_info, UUID):
6970
+ service_connectors.append(
6971
+ self.get_service_connector(connector_id_or_info)
6972
+ )
6973
+ # Create a new service connector
6974
+ else:
6975
+ connector_name = full_stack.name
6976
+ while True:
6977
+ try:
6978
+ service_connector_request = ServiceConnectorRequest(
6979
+ name=connector_name,
6980
+ connector_type=connector_id_or_info.type,
6981
+ auth_method=connector_id_or_info.auth_method,
6982
+ configuration=connector_id_or_info.configuration,
6983
+ user=full_stack.user,
6984
+ workspace=full_stack.workspace,
6985
+ labels={
6986
+ k: str(v)
6987
+ for k, v in full_stack.labels.items()
6988
+ },
6989
+ )
6990
+ service_connector_response = (
6991
+ self.create_service_connector(
6992
+ service_connector=service_connector_request
6993
+ )
6994
+ )
6995
+ service_connectors.append(
6996
+ service_connector_response
6997
+ )
6998
+ service_connectors_created_ids.append(
6999
+ service_connector_response.id
7000
+ )
7001
+ break
7002
+ except EntityExistsError:
7003
+ connector_name = (
7004
+ f"{full_stack.name}-{random_str(4)}".lower()
7005
+ )
7006
+ continue
7007
+
7008
+ # Stack Components
7009
+ components_mapping: Dict[StackComponentType, List[UUID]] = {}
7010
+ for (
7011
+ component_type,
7012
+ component_info,
7013
+ ) in full_stack.components.items():
7014
+ # Fetch an existing component
7015
+ if isinstance(component_info, UUID):
7016
+ component = self.get_stack_component(
7017
+ component_id=component_info
7018
+ )
7019
+ # Create a new component
7020
+ else:
7021
+ flavor_list = self.list_flavors(
7022
+ flavor_filter_model=FlavorFilter(
7023
+ name=component_info.flavor,
7024
+ type=component_type,
7025
+ )
7026
+ )
7027
+ if not len(flavor_list):
7028
+ raise ValueError(
7029
+ f"Flavor '{component_info.flavor}' not found "
7030
+ f"for component type '{component_type}'."
7031
+ )
7032
+
7033
+ flavor_model = flavor_list[0]
7034
+
7035
+ component_name = full_stack.name
7036
+ while True:
7037
+ try:
7038
+ component_request = ComponentRequest(
7039
+ name=component_name,
7040
+ type=component_type,
7041
+ flavor=component_info.flavor,
7042
+ configuration=component_info.configuration,
7043
+ user=full_stack.user,
7044
+ workspace=full_stack.workspace,
7045
+ labels=full_stack.labels,
7046
+ )
7047
+ component = self.create_stack_component(
7048
+ component=component_request
7049
+ )
7050
+ components_created_ids.append(component.id)
7051
+ break
7052
+ except EntityExistsError:
7053
+ component_name = (
7054
+ f"{full_stack.name}-{random_str(4)}".lower()
7055
+ )
7056
+ continue
7057
+
7058
+ if component_info.service_connector_index is not None:
7059
+ service_connector = service_connectors[
7060
+ component_info.service_connector_index
7061
+ ]
7062
+
7063
+ requirements = flavor_model.connector_requirements
7064
+
7065
+ if not requirements:
7066
+ raise ValueError(
7067
+ f"The '{flavor_model.name}' implementation "
7068
+ "does not support using a service connector to "
7069
+ "connect to resources."
7070
+ )
7071
+
7072
+ if component_info.service_connector_resource_id:
7073
+ resource_id = (
7074
+ component_info.service_connector_resource_id
7075
+ )
7076
+ else:
7077
+ resource_id = None
7078
+ resource_type = requirements.resource_type
7079
+ if requirements.resource_id_attr is not None:
7080
+ resource_id = component_info.configuration.get(
7081
+ requirements.resource_id_attr
7082
+ )
7083
+
7084
+ satisfied, msg = requirements.is_satisfied_by(
7085
+ connector=service_connector,
7086
+ component=component,
7087
+ )
7088
+
7089
+ if not satisfied:
7090
+ raise ValueError(
7091
+ "Please pick a connector that is "
7092
+ "compatible with the component flavor and "
7093
+ "try again.."
7094
+ )
7095
+
7096
+ if not resource_id:
7097
+ if service_connector.resource_id:
7098
+ resource_id = service_connector.resource_id
7099
+ elif service_connector.supports_instances:
7100
+ raise ValueError(
7101
+ f"Multiple {resource_type} resources "
7102
+ "are available for the selected "
7103
+ "connector. Please use a `resource_id` "
7104
+ "to configure a "
7105
+ f"{resource_type} resource."
7106
+ )
7107
+
7108
+ component_update = ComponentUpdate(
7109
+ connector=service_connector.id,
7110
+ connector_resource_id=resource_id,
7111
+ )
7112
+ self.update_stack_component(
7113
+ component_id=component.id,
7114
+ component_update=component_update,
7115
+ )
7116
+
7117
+ components_mapping[component_type] = [
7118
+ component.id,
7119
+ ]
7120
+
7121
+ # Stack
7122
+ stack_name = full_stack.name
7123
+ while True:
7124
+ try:
7125
+ stack_request = StackRequest(
7126
+ user=full_stack.user,
7127
+ workspace=full_stack.workspace,
7128
+ name=stack_name,
7129
+ description=full_stack.description,
7130
+ components=components_mapping,
7131
+ labels=full_stack.labels,
7132
+ )
7133
+ stack_response = self.create_stack(stack_request)
7134
+
7135
+ break
7136
+ except EntityExistsError:
7137
+ stack_name = f"{full_stack.name}-{random_str(4)}".lower()
7138
+
7139
+ return stack_response
7140
+
7141
+ except Exception as e:
7142
+ for component_id in components_created_ids:
7143
+ self.delete_stack_component(component_id=component_id)
7144
+ for service_connector_id in service_connectors_created_ids:
7145
+ self.delete_service_connector(
7146
+ service_connector_id=service_connector_id
7147
+ )
7148
+ raise RuntimeError(
7149
+ f"Full Stack creation has failed {e}. Cleaning up the "
7150
+ f"created entities."
7151
+ ) from e
7152
+
6922
7153
  def get_stack(self, stack_id: UUID, hydrate: bool = True) -> StackResponse:
6923
7154
  """Get a stack by its unique ID.
6924
7155
 
@@ -7195,6 +7426,69 @@ class SqlZenStore(BaseZenStore):
7195
7426
  workspace_id=workspace.id,
7196
7427
  )
7197
7428
 
7429
+ # ---------------- Stack deployments-----------------
7430
+
7431
+ def get_stack_deployment_info(
7432
+ self,
7433
+ provider: StackDeploymentProvider,
7434
+ ) -> StackDeploymentInfo:
7435
+ """Get information about a stack deployment provider.
7436
+
7437
+ Args:
7438
+ provider: The stack deployment provider.
7439
+
7440
+ Raises:
7441
+ NotImplementedError: Stack deployments are not supported by the
7442
+ local ZenML deployment.
7443
+ """
7444
+ raise NotImplementedError(
7445
+ "Stack deployments are not supported by local ZenML deployments."
7446
+ )
7447
+
7448
+ def get_stack_deployment_config(
7449
+ self,
7450
+ provider: StackDeploymentProvider,
7451
+ stack_name: str,
7452
+ location: Optional[str] = None,
7453
+ ) -> StackDeploymentConfig:
7454
+ """Return the cloud provider console URL and configuration needed to deploy the ZenML stack.
7455
+
7456
+ Args:
7457
+ provider: The stack deployment provider.
7458
+ stack_name: The name of the stack.
7459
+ location: The location where the stack should be deployed.
7460
+
7461
+ Raises:
7462
+ NotImplementedError: Stack deployments are not supported by the
7463
+ local ZenML deployment.
7464
+ """
7465
+ raise NotImplementedError(
7466
+ "Stack deployments are not supported by local ZenML deployments."
7467
+ )
7468
+
7469
+ def get_stack_deployment_stack(
7470
+ self,
7471
+ provider: StackDeploymentProvider,
7472
+ stack_name: str,
7473
+ location: Optional[str] = None,
7474
+ date_start: Optional[datetime] = None,
7475
+ ) -> Optional[DeployedStack]:
7476
+ """Return a matching ZenML stack that was deployed and registered.
7477
+
7478
+ Args:
7479
+ provider: The stack deployment provider.
7480
+ stack_name: The name of the stack.
7481
+ location: The location where the stack should be deployed.
7482
+ date_start: The date when the deployment started.
7483
+
7484
+ Raises:
7485
+ NotImplementedError: Stack deployments are not supported by the
7486
+ local ZenML deployment.
7487
+ """
7488
+ raise NotImplementedError(
7489
+ "Stack deployments are not supported by local ZenML deployments."
7490
+ )
7491
+
7198
7492
  # ----------------------------- Step runs -----------------------------
7199
7493
 
7200
7494
  def create_run_step(self, step_run: StepRunRequest) -> StepRunResponse:
@@ -13,11 +13,13 @@
13
13
  # permissions and limitations under the License.
14
14
  """ZenML Store interface."""
15
15
 
16
+ import datetime
16
17
  from abc import ABC, abstractmethod
17
18
  from typing import List, Optional, Tuple, Union
18
19
  from uuid import UUID
19
20
 
20
21
  from zenml.config.pipeline_run_configuration import PipelineRunConfiguration
22
+ from zenml.enums import StackDeploymentProvider
21
23
  from zenml.models import (
22
24
  ActionFilter,
23
25
  ActionRequest,
@@ -46,6 +48,7 @@ from zenml.models import (
46
48
  ComponentRequest,
47
49
  ComponentResponse,
48
50
  ComponentUpdate,
51
+ DeployedStack,
49
52
  EventSourceFilter,
50
53
  EventSourceRequest,
51
54
  EventSourceResponse,
@@ -54,6 +57,7 @@ from zenml.models import (
54
57
  FlavorRequest,
55
58
  FlavorResponse,
56
59
  FlavorUpdate,
60
+ FullStackRequest,
57
61
  LogsResponse,
58
62
  ModelFilter,
59
63
  ModelRequest,
@@ -115,6 +119,8 @@ from zenml.models import (
115
119
  ServiceRequest,
116
120
  ServiceResponse,
117
121
  ServiceUpdate,
122
+ StackDeploymentConfig,
123
+ StackDeploymentInfo,
118
124
  StackFilter,
119
125
  StackRequest,
120
126
  StackResponse,
@@ -2166,6 +2172,24 @@ class ZenStoreInterface(ABC):
2166
2172
  by this user in this workspace.
2167
2173
  """
2168
2174
 
2175
+ @abstractmethod
2176
+ def create_full_stack(self, full_stack: FullStackRequest) -> StackResponse:
2177
+ """Create a full stack.
2178
+
2179
+ Args:
2180
+ full_stack: The full stack configuration.
2181
+
2182
+ Returns:
2183
+ The created stack.
2184
+
2185
+ Raises:
2186
+ EntityExistsError: If a service connector with the same name
2187
+ already exists.
2188
+ StackComponentExistsError: If a stack component with the same name
2189
+ already exists.
2190
+ StackExistsError: If a stack with the same name already exists.
2191
+ """
2192
+
2169
2193
  @abstractmethod
2170
2194
  def get_stack(self, stack_id: UUID, hydrate: bool = True) -> StackResponse:
2171
2195
  """Get a stack by its unique ID.
@@ -2228,6 +2252,62 @@ class ZenStoreInterface(ABC):
2228
2252
  KeyError: if the stack doesn't exist.
2229
2253
  """
2230
2254
 
2255
+ # ---------------- Stack deployments-----------------
2256
+
2257
+ @abstractmethod
2258
+ def get_stack_deployment_info(
2259
+ self,
2260
+ provider: StackDeploymentProvider,
2261
+ ) -> StackDeploymentInfo:
2262
+ """Get information about a stack deployment provider.
2263
+
2264
+ Args:
2265
+ provider: The stack deployment provider.
2266
+
2267
+ Returns:
2268
+ Information about the stack deployment provider.
2269
+ """
2270
+
2271
+ @abstractmethod
2272
+ def get_stack_deployment_config(
2273
+ self,
2274
+ provider: StackDeploymentProvider,
2275
+ stack_name: str,
2276
+ location: Optional[str] = None,
2277
+ ) -> StackDeploymentConfig:
2278
+ """Return the cloud provider console URL and configuration needed to deploy the ZenML stack.
2279
+
2280
+ Args:
2281
+ provider: The stack deployment provider.
2282
+ stack_name: The name of the stack.
2283
+ location: The location where the stack should be deployed.
2284
+
2285
+ Returns:
2286
+ The cloud provider console URL and configuration needed to deploy
2287
+ the ZenML stack to the specified cloud provider.
2288
+ """
2289
+
2290
+ @abstractmethod
2291
+ def get_stack_deployment_stack(
2292
+ self,
2293
+ provider: StackDeploymentProvider,
2294
+ stack_name: str,
2295
+ location: Optional[str] = None,
2296
+ date_start: Optional[datetime.datetime] = None,
2297
+ ) -> Optional[DeployedStack]:
2298
+ """Return a matching ZenML stack that was deployed and registered.
2299
+
2300
+ Args:
2301
+ provider: The stack deployment provider.
2302
+ stack_name: The name of the stack.
2303
+ location: The location where the stack should be deployed.
2304
+ date_start: The date when the deployment started.
2305
+
2306
+ Returns:
2307
+ The ZenML stack that was deployed and registered or None if the
2308
+ stack was not found.
2309
+ """
2310
+
2231
2311
  # -------------------- Step runs --------------------
2232
2312
 
2233
2313
  @abstractmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zenml-nightly
3
- Version: 0.58.2.dev20240626
3
+ Version: 0.61.0.dev20240712
4
4
  Summary: ZenML: Write production-ready ML code.
5
5
  Home-page: https://zenml.io
6
6
  License: Apache-2.0
@@ -63,6 +63,7 @@ Requires-Dist: docker (>=6.1.0,<6.2.0)
63
63
  Requires-Dist: fastapi (>=0.100,<=0.110) ; extra == "server"
64
64
  Requires-Dist: gcsfs (>=2022.11.0) ; extra == "gcsfs"
65
65
  Requires-Dist: gitpython (>=3.1.18,<4.0.0)
66
+ Requires-Dist: google-cloud-artifact-registry (>=1.11.3) ; extra == "connectors-gcp"
66
67
  Requires-Dist: google-cloud-container (>=2.21.0) ; extra == "connectors-gcp"
67
68
  Requires-Dist: google-cloud-secret-manager (>=2.12.5) ; extra == "secrets-gcp"
68
69
  Requires-Dist: google-cloud-storage (>=2.9.0) ; extra == "connectors-gcp"
@@ -272,9 +273,36 @@ if __name__ == "__main__":
272
273
 
273
274
  ![Running a ZenML pipeline](/docs/book/.gitbook/assets/readme_basic_pipeline.gif)
274
275
 
275
- ### Deploy workloads easily on your production infrastructure
276
+ ### Easily provision an MLOps stack or reuse your existing infrastructure
276
277
 
277
- The framework is a gentle entry point for practitioners to build complex ML pipelines with little knowledge required of the underlying infrastructure complexity. ZenML pipelines can be run on AWS, GCP, Azure, Airflow, Kubeflow and even on Kubernetes without having to change any code or know underlying internals.
278
+ The framework is a gentle entry point for practitioners to build complex ML pipelines with little knowledge required of the underlying infrastructure complexity. ZenML pipelines can be run on AWS, GCP, Azure, Airflow, Kubeflow and even on Kubernetes without having to change any code or know underlying internals.
279
+
280
+ ZenML provides different features to aid people to get started quickly on a remote setting as well. If you want to deploy a remote stack from scratch on your selected cloud provider, you can use the 1-click deployment feature either through the dashboard:
281
+
282
+ ![Running a ZenML pipeline](/docs/book/.gitbook/assets/one-click-deployment.gif)
283
+
284
+ Or, through our CLI command:
285
+
286
+ ```bash
287
+ zenml stack deploy --provider aws
288
+ ```
289
+
290
+ Alternatively, if the necessary pieces of infrastructure is already deployed, you can register a cloud stack seamlessly through the stack wizard:
291
+
292
+ ```bash
293
+ zenml stack register <STACK_NAME> --provider aws
294
+ ```
295
+
296
+ Read more about [ZenML stacks](https://docs.zenml.io/user-guide/production-guide/understand-stacks).
297
+
298
+ ### Run workloads easily on your production infrastructure
299
+
300
+ Once you have your MLOps stack configured, you can easily run workloads on it:
301
+
302
+ ```bash
303
+ zenml stack set <STACK_NAME>
304
+ python run.py
305
+ ```
278
306
 
279
307
  ```python
280
308
  from zenml.config import ResourceSettings, DockerSettings
@@ -289,14 +317,8 @@ def training(...):
289
317
  ...
290
318
  ```
291
319
 
292
- ```bash
293
- zenml stack set k8s # Set a stack with kubernetes orchestrator
294
- python run.py
295
- ```
296
-
297
320
  ![Workloads with ZenML](/docs/book/.gitbook/assets/readme_compute.gif)
298
321
 
299
-
300
322
  ### Track models, pipeline, and artifacts
301
323
 
302
324
  Create a complete lineage of who, where, and what data and models are produced.
@@ -445,7 +467,7 @@ the Apache License Version 2.0.
445
467
  <a href="https://github.com/zenml-io/zenml-projects">Projects Showcase</a>
446
468
  <br />
447
469
  <br />
448
- 🎉 Version 0.58.2 is out. Check out the release notes
470
+ 🎉 Version 0.61.0 is out. Check out the release notes
449
471
  <a href="https://github.com/zenml-io/zenml/releases">here</a>.
450
472
  <br />
451
473
  🖥️ Download our VS Code Extension <a href="https://marketplace.visualstudio.com/items?itemName=ZenML.zenml-vscode">here</a>.