zenml-nightly 0.58.2.dev20240623__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 (249) hide show
  1. README.md +30 -9
  2. RELEASE_NOTES.md +240 -0
  3. zenml/VERSION +1 -1
  4. zenml/actions/base_action.py +177 -174
  5. zenml/actions/pipeline_run/pipeline_run_action.py +28 -23
  6. zenml/analytics/enums.py +3 -0
  7. zenml/artifact_stores/base_artifact_store.py +7 -1
  8. zenml/artifacts/utils.py +13 -10
  9. zenml/cli/__init__.py +28 -0
  10. zenml/cli/artifact.py +1 -2
  11. zenml/cli/integration.py +9 -8
  12. zenml/cli/server.py +6 -0
  13. zenml/cli/service_connectors.py +1 -0
  14. zenml/cli/stack.py +946 -39
  15. zenml/cli/stack_components.py +7 -0
  16. zenml/cli/text_utils.py +35 -1
  17. zenml/cli/utils.py +127 -10
  18. zenml/client.py +257 -72
  19. zenml/config/compiler.py +10 -9
  20. zenml/config/docker_settings.py +33 -14
  21. zenml/constants.py +11 -2
  22. zenml/container_registries/base_container_registry.py +1 -0
  23. zenml/enums.py +7 -0
  24. zenml/event_hub/base_event_hub.py +5 -5
  25. zenml/event_hub/event_hub.py +20 -14
  26. zenml/event_sources/base_event.py +0 -11
  27. zenml/event_sources/base_event_source.py +7 -0
  28. zenml/event_sources/webhooks/base_webhook_event_source.py +1 -4
  29. zenml/exceptions.py +4 -0
  30. zenml/hooks/hook_validators.py +2 -3
  31. zenml/integrations/aws/__init__.py +1 -0
  32. zenml/integrations/azure/__init__.py +1 -0
  33. zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +3 -3
  34. zenml/integrations/deepchecks/__init__.py +1 -0
  35. zenml/integrations/discord/__init__.py +1 -0
  36. zenml/integrations/evidently/__init__.py +1 -0
  37. zenml/integrations/facets/__init__.py +1 -0
  38. zenml/integrations/feast/__init__.py +1 -0
  39. zenml/integrations/gcp/__init__.py +3 -1
  40. zenml/integrations/gcp/google_credentials_mixin.py +1 -1
  41. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +320 -64
  42. zenml/integrations/huggingface/__init__.py +1 -0
  43. zenml/integrations/integration.py +24 -0
  44. zenml/integrations/kubeflow/__init__.py +3 -0
  45. zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +1 -1
  46. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +0 -1
  47. zenml/integrations/kubernetes/__init__.py +3 -1
  48. zenml/integrations/kubernetes/orchestrators/kube_utils.py +4 -1
  49. zenml/integrations/label_studio/annotators/label_studio_annotator.py +1 -0
  50. zenml/integrations/langchain/__init__.py +1 -0
  51. zenml/integrations/mlflow/__init__.py +4 -2
  52. zenml/integrations/neural_prophet/__init__.py +1 -0
  53. zenml/integrations/polars/__init__.py +1 -0
  54. zenml/integrations/prodigy/__init__.py +1 -0
  55. zenml/integrations/pycaret/__init__.py +6 -0
  56. zenml/integrations/registry.py +37 -0
  57. zenml/integrations/s3/artifact_stores/s3_artifact_store.py +93 -9
  58. zenml/integrations/seldon/__init__.py +1 -0
  59. zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -0
  60. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +2 -2
  61. zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +1 -1
  62. zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py +2 -2
  63. zenml/integrations/skypilot_aws/__init__.py +2 -1
  64. zenml/integrations/skypilot_azure/__init__.py +1 -1
  65. zenml/integrations/skypilot_gcp/__init__.py +1 -1
  66. zenml/integrations/skypilot_lambda/__init__.py +1 -1
  67. zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +1 -1
  68. zenml/integrations/slack/__init__.py +1 -0
  69. zenml/integrations/tekton/__init__.py +1 -0
  70. zenml/integrations/tensorboard/__init__.py +0 -1
  71. zenml/integrations/tensorflow/__init__.py +18 -6
  72. zenml/integrations/wandb/__init__.py +1 -0
  73. zenml/logging/step_logging.py +54 -51
  74. zenml/models/__init__.py +28 -0
  75. zenml/models/v2/core/action.py +276 -0
  76. zenml/models/v2/core/component.py +18 -0
  77. zenml/models/v2/core/model.py +1 -2
  78. zenml/models/v2/core/service_connector.py +17 -0
  79. zenml/models/v2/core/stack.py +31 -0
  80. zenml/models/v2/core/trigger.py +182 -141
  81. zenml/models/v2/misc/full_stack.py +97 -0
  82. zenml/models/v2/misc/stack_deployment.py +86 -0
  83. zenml/new/pipelines/pipeline.py +14 -4
  84. zenml/new/pipelines/pipeline_decorator.py +1 -2
  85. zenml/new/pipelines/run_utils.py +1 -12
  86. zenml/new/steps/step_decorator.py +2 -3
  87. zenml/orchestrators/input_utils.py +3 -6
  88. zenml/pipelines/base_pipeline.py +0 -2
  89. zenml/pipelines/pipeline_decorator.py +1 -2
  90. zenml/stack/stack.py +3 -6
  91. zenml/stack/stack_component.py +4 -0
  92. zenml/stack_deployments/__init__.py +14 -0
  93. zenml/stack_deployments/aws_stack_deployment.py +254 -0
  94. zenml/stack_deployments/gcp_stack_deployment.py +260 -0
  95. zenml/stack_deployments/stack_deployment.py +208 -0
  96. zenml/stack_deployments/utils.py +44 -0
  97. zenml/steps/base_step.py +1 -2
  98. zenml/steps/step_decorator.py +1 -2
  99. zenml/types.py +10 -1
  100. zenml/utils/function_utils.py +1 -1
  101. zenml/utils/pagination_utils.py +7 -5
  102. zenml/utils/pipeline_docker_image_builder.py +117 -73
  103. zenml/utils/pydantic_utils.py +6 -5
  104. zenml/zen_server/cloud_utils.py +18 -3
  105. zenml/zen_server/dashboard/assets/{404-CDPQCl4D.js → 404-DpJaNHKF.js} +1 -1
  106. zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +85 -0
  107. zenml/zen_server/dashboard/assets/{@react-router-DYovave8.js → @react-router-CO-OsFwI.js} +2 -2
  108. zenml/zen_server/dashboard/assets/{@reactflow-CHBapDaj.js → @reactflow-DJfzkHO1.js} +2 -2
  109. zenml/zen_server/dashboard/assets/@tanstack-DYiOyJUL.js +22 -0
  110. zenml/zen_server/dashboard/assets/AwarenessChannel-BYDLT2xC.js +1 -0
  111. zenml/zen_server/dashboard/assets/{CodeSnippet-BidtnWOi.js → CodeSnippet-BkOuRmyq.js} +2 -2
  112. zenml/zen_server/dashboard/assets/Commands-ZvWR1BRs.js +1 -0
  113. zenml/zen_server/dashboard/assets/CopyButton-DVwLkafa.js +2 -0
  114. zenml/zen_server/dashboard/assets/{CsvVizualization-BOuez-fG.js → CsvVizualization-C2IiqX4I.js} +7 -7
  115. zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +1 -0
  116. zenml/zen_server/dashboard/assets/EmptyState-BMLnFVlB.js +1 -0
  117. zenml/zen_server/dashboard/assets/Error-CqX0VqW_.js +1 -0
  118. zenml/zen_server/dashboard/assets/ExecutionStatus-BoLUXR9t.js +1 -0
  119. zenml/zen_server/dashboard/assets/Helpbox-LFydyVwh.js +1 -0
  120. zenml/zen_server/dashboard/assets/Infobox-DnENC0sh.js +1 -0
  121. zenml/zen_server/dashboard/assets/InlineAvatar-CbJtYr0t.js +1 -0
  122. zenml/zen_server/dashboard/assets/{MarkdownVisualization-DsB2QZiK.js → MarkdownVisualization-xp3hhULl.js} +2 -2
  123. zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +1 -0
  124. zenml/zen_server/dashboard/assets/PasswordChecker-DUveqlva.js +1 -0
  125. zenml/zen_server/dashboard/assets/SetPassword-BYBdbQDo.js +1 -0
  126. zenml/zen_server/dashboard/assets/SuccessStep-Nx743hll.js +1 -0
  127. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DnM-c11H.js → UpdatePasswordSchemas-DF9gSzE0.js} +1 -1
  128. zenml/zen_server/dashboard/assets/{aws-t0gKCj_R.js → aws-BgKTfTfx.js} +1 -1
  129. zenml/zen_server/dashboard/assets/{check-circle-BVvhm5dy.js → check-circle-i56092KI.js} +1 -1
  130. zenml/zen_server/dashboard/assets/{chevron-down-zcvCWmyP.js → chevron-down-D_ZlKMqH.js} +1 -1
  131. zenml/zen_server/dashboard/assets/{chevron-right-double-CJ50E9Gr.js → chevron-right-double-BiEMg7rd.js} +1 -1
  132. zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +1 -0
  133. zenml/zen_server/dashboard/assets/{copy-BRhQz3j-.js → copy-BXNk6BjL.js} +1 -1
  134. zenml/zen_server/dashboard/assets/{database-CRRnyFWh.js → database-1xWSgZfO.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{docker-BAonhm6G.js → docker-CQMVm_4d.js} +1 -1
  136. zenml/zen_server/dashboard/assets/{file-text-CbVERUON.js → file-text-CqD_iu6l.js} +1 -1
  137. zenml/zen_server/dashboard/assets/{help-B8rqCvqn.js → help-bu_DgLKI.js} +1 -1
  138. zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +1 -0
  139. zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +55 -0
  140. zenml/zen_server/dashboard/assets/index-inApY3KQ.css +1 -0
  141. zenml/zen_server/dashboard/assets/index-rK_Wuy2W.js +1 -0
  142. zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +1 -0
  143. zenml/zen_server/dashboard/assets/{login-mutation-wzzl23C6.js → login-mutation-BUnVASxp.js} +1 -1
  144. zenml/zen_server/dashboard/assets/not-found-B4VnX8gK.js +1 -0
  145. zenml/zen_server/dashboard/assets/package-CsUhPmou.js +1 -0
  146. zenml/zen_server/dashboard/assets/{page-BmkSiYeQ.js → page-3efNCDeb.js} +2 -2
  147. zenml/zen_server/dashboard/assets/page-7zTHbhhI.js +1 -0
  148. zenml/zen_server/dashboard/assets/page-BEs6jK71.js +1 -0
  149. zenml/zen_server/dashboard/assets/page-BpSqIf4B.js +1 -0
  150. zenml/zen_server/dashboard/assets/{page-AQKopn_4.js → page-Bx6o0ARS.js} +1 -1
  151. zenml/zen_server/dashboard/assets/page-C43QGHTt.js +9 -0
  152. zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +1 -0
  153. zenml/zen_server/dashboard/assets/page-CRTJ0UuR.js +1 -0
  154. zenml/zen_server/dashboard/assets/page-CUZIGO-3.js +1 -0
  155. zenml/zen_server/dashboard/assets/page-CaopxiU1.js +1 -0
  156. zenml/zen_server/dashboard/assets/{page-CuT1SUik.js → page-Cx67M0QT.js} +1 -1
  157. zenml/zen_server/dashboard/assets/page-D7Z399xy.js +1 -0
  158. zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +1 -0
  159. zenml/zen_server/dashboard/assets/{page-BzVZGExK.js → page-DKlIdAe5.js} +1 -1
  160. zenml/zen_server/dashboard/assets/{page-Bi5AI0S7.js → page-DMOYZppS.js} +1 -1
  161. zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +2 -0
  162. zenml/zen_server/dashboard/assets/{page-BW6Ket3a.js → page-Dc_7KMQE.js} +1 -1
  163. zenml/zen_server/dashboard/assets/page-DvCvroOM.js +1 -0
  164. zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +1 -0
  165. zenml/zen_server/dashboard/assets/page-JyfeDUfu.js +1 -0
  166. zenml/zen_server/dashboard/assets/{page-yN4rZ-ZS.js → page-Sxn82W-5.js} +1 -1
  167. zenml/zen_server/dashboard/assets/page-TKXERe16.js +1 -0
  168. zenml/zen_server/dashboard/assets/page-Xu8JEjSU.js +1 -0
  169. zenml/zen_server/dashboard/assets/{play-circle-DK5QMJyp.js → play-circle-CNtZKDnW.js} +1 -1
  170. zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +1 -0
  171. zenml/zen_server/dashboard/assets/{terminal-B2ovgWuz.js → terminal-By9cErXc.js} +1 -1
  172. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-0Wgz8pUE.js → update-server-settings-mutation-CR8e3Sir.js} +1 -1
  173. zenml/zen_server/dashboard/assets/{url-6_xv0WJS.js → url-DuQMeqYA.js} +1 -1
  174. zenml/zen_server/dashboard/assets/{zod-DrZvVLjd.js → zod-BhoGpZ63.js} +1 -1
  175. zenml/zen_server/dashboard/index.html +7 -7
  176. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  177. zenml/zen_server/dashboard_legacy/index.html +1 -1
  178. zenml/zen_server/dashboard_legacy/{precache-manifest.f4abc5b7cfa7d90c1caf5521918e29a8.js → precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js} +4 -4
  179. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  180. zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js → main.382439a7.chunk.js} +2 -2
  181. zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js.map → main.382439a7.chunk.js.map} +1 -1
  182. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  183. zenml/zen_server/deploy/helm/README.md +2 -2
  184. zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +11 -5
  185. zenml/zen_server/pipeline_deployment/utils.py +57 -44
  186. zenml/zen_server/rbac/models.py +1 -0
  187. zenml/zen_server/rbac/utils.py +22 -1
  188. zenml/zen_server/rbac/zenml_cloud_rbac.py +11 -5
  189. zenml/zen_server/routers/actions_endpoints.py +324 -0
  190. zenml/zen_server/routers/stack_deployment_endpoints.py +158 -0
  191. zenml/zen_server/routers/triggers_endpoints.py +30 -158
  192. zenml/zen_server/routers/workspaces_endpoints.py +64 -0
  193. zenml/zen_server/zen_server_api.py +4 -0
  194. zenml/zen_stores/migrations/utils.py +1 -1
  195. zenml/zen_stores/migrations/versions/0.60.0_release.py +23 -0
  196. zenml/zen_stores/migrations/versions/0.61.0_release.py +23 -0
  197. zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
  198. zenml/zen_stores/migrations/versions/25155145c545_separate_actions_and_triggers.py +228 -0
  199. zenml/zen_stores/rest_zen_store.py +248 -8
  200. zenml/zen_stores/schemas/__init__.py +2 -0
  201. zenml/zen_stores/schemas/action_schemas.py +192 -0
  202. zenml/zen_stores/schemas/stack_schemas.py +10 -0
  203. zenml/zen_stores/schemas/step_run_schemas.py +27 -11
  204. zenml/zen_stores/schemas/trigger_schemas.py +43 -50
  205. zenml/zen_stores/schemas/user_schemas.py +10 -2
  206. zenml/zen_stores/schemas/workspace_schemas.py +5 -0
  207. zenml/zen_stores/sql_zen_store.py +540 -36
  208. zenml/zen_stores/zen_store_interface.py +165 -0
  209. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/METADATA +33 -11
  210. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/RECORD +213 -193
  211. zenml/zen_server/dashboard/assets/@radix-C9DBgJhe.js +0 -77
  212. zenml/zen_server/dashboard/assets/@tanstack-CEbkxrhX.js +0 -30
  213. zenml/zen_server/dashboard/assets/AwarenessChannel-nXGpmj_f.js +0 -1
  214. zenml/zen_server/dashboard/assets/Cards-nwsvQLVS.js +0 -1
  215. zenml/zen_server/dashboard/assets/Commands-DuIWKg_Q.js +0 -1
  216. zenml/zen_server/dashboard/assets/CopyButton-B_YSm-Ds.js +0 -2
  217. zenml/zen_server/dashboard/assets/DisplayDate-BdguISQF.js +0 -1
  218. zenml/zen_server/dashboard/assets/EmptyState-BkooiGtL.js +0 -1
  219. zenml/zen_server/dashboard/assets/Error-B6M0dPph.js +0 -1
  220. zenml/zen_server/dashboard/assets/Helpbox-BQoqCm04.js +0 -1
  221. zenml/zen_server/dashboard/assets/Infobox-Ce9mefqU.js +0 -1
  222. zenml/zen_server/dashboard/assets/InlineAvatar-DGf3dVhV.js +0 -1
  223. zenml/zen_server/dashboard/assets/PageHeader-DGaemzjc.js +0 -1
  224. zenml/zen_server/dashboard/assets/Pagination-DVYfBCCc.js +0 -1
  225. zenml/zen_server/dashboard/assets/PasswordChecker-DSLBp7Vl.js +0 -1
  226. zenml/zen_server/dashboard/assets/SetPassword-B5s7DJug.js +0 -1
  227. zenml/zen_server/dashboard/assets/SuccessStep-ZzczaM7g.js +0 -1
  228. zenml/zen_server/dashboard/assets/cloud-only-Ba_ShBR5.js +0 -1
  229. zenml/zen_server/dashboard/assets/index-CWJ3xbIf.css +0 -1
  230. zenml/zen_server/dashboard/assets/index-QORVVTMN.js +0 -55
  231. zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +0 -1
  232. zenml/zen_server/dashboard/assets/not-found-Dh2la7kh.js +0 -1
  233. zenml/zen_server/dashboard/assets/page-B-5jAKoO.js +0 -1
  234. zenml/zen_server/dashboard/assets/page-B-vWk8a6.js +0 -1
  235. zenml/zen_server/dashboard/assets/page-B0BrqfS8.js +0 -1
  236. zenml/zen_server/dashboard/assets/page-BQxVFlUl.js +0 -1
  237. zenml/zen_server/dashboard/assets/page-ByrHy6Ss.js +0 -1
  238. zenml/zen_server/dashboard/assets/page-CPtY4Kv_.js +0 -1
  239. zenml/zen_server/dashboard/assets/page-CmmukLsl.js +0 -1
  240. zenml/zen_server/dashboard/assets/page-D2D-7qyr.js +0 -9
  241. zenml/zen_server/dashboard/assets/page-DAQQyLxT.js +0 -1
  242. zenml/zen_server/dashboard/assets/page-DHkUMl_E.js +0 -1
  243. zenml/zen_server/dashboard/assets/page-DZCbwOEs.js +0 -2
  244. zenml/zen_server/dashboard/assets/page-DdaIt20-.js +0 -1
  245. zenml/zen_server/dashboard/assets/page-LqLs24Ot.js +0 -1
  246. zenml/zen_server/dashboard/assets/page-lebv0c7C.js +0 -1
  247. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/LICENSE +0 -0
  248. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/WHEEL +0 -0
  249. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  apiVersion: v2
2
2
  name: zenml
3
- version: "0.58.2"
3
+ version: "0.61.0"
4
4
  description: Open source MLOps framework for portable production ready ML pipelines
5
5
  keywords:
6
6
  - mlops
@@ -20,8 +20,8 @@ ZenML is an open-source MLOps framework designed to help you create robust, main
20
20
  To install the ZenML chart directly from Amazon ECR, use the following command:
21
21
 
22
22
  ```bash
23
- # example command for version 0.58.2
24
- helm install my-zenml oci://public.ecr.aws/zenml/zenml --version 0.58.2
23
+ # example command for version 0.61.0
24
+ helm install my-zenml oci://public.ecr.aws/zenml/zenml --version 0.61.0
25
25
  ```
26
26
 
27
27
  Note: Ensure you have OCI support enabled in your Helm client and that you are authenticated with Amazon ECR.
@@ -21,7 +21,7 @@ from pydantic import BaseModel, Field
21
21
  from zenml.config.server_config import ServerConfiguration
22
22
  from zenml.exceptions import SubscriptionUpgradeRequiredError
23
23
  from zenml.logger import get_logger
24
- from zenml.zen_server.cloud_utils import ZenMLCloudSession
24
+ from zenml.zen_server.cloud_utils import cloud_connection
25
25
  from zenml.zen_server.feature_gate.feature_gate_interface import (
26
26
  FeatureGateInterface,
27
27
  )
@@ -59,8 +59,12 @@ class RawUsageEvent(BaseModel):
59
59
  )
60
60
 
61
61
 
62
- class ZenMLCloudFeatureGateInterface(FeatureGateInterface, ZenMLCloudSession):
63
- """Feature Gate interface definition."""
62
+ class ZenMLCloudFeatureGateInterface(FeatureGateInterface):
63
+ """ZenML Cloud Feature Gate implementation."""
64
+
65
+ def __init__(self) -> None:
66
+ """Initialize the object."""
67
+ self._connection = cloud_connection()
64
68
 
65
69
  def check_entitlement(self, resource: ResourceType) -> None:
66
70
  """Checks if a user is entitled to create a resource.
@@ -72,7 +76,7 @@ class ZenMLCloudFeatureGateInterface(FeatureGateInterface, ZenMLCloudSession):
72
76
  SubscriptionUpgradeRequiredError: in case a subscription limit is reached
73
77
  """
74
78
  try:
75
- response = self._get(
79
+ response = self._connection.get(
76
80
  endpoint=ENTITLEMENT_ENDPOINT + "/" + resource, params=None
77
81
  )
78
82
  except SubscriptionUpgradeRequiredError:
@@ -110,7 +114,9 @@ class ZenMLCloudFeatureGateInterface(FeatureGateInterface, ZenMLCloudSession):
110
114
  "resource_id": str(resource_id),
111
115
  },
112
116
  ).model_dump()
113
- response = self._post(endpoint=USAGE_EVENT_ENDPOINT, data=data)
117
+ response = self._connection.post(
118
+ endpoint=USAGE_EVENT_ENDPOINT, data=data
119
+ )
114
120
  if response.status_code != 200:
115
121
  logger.error(
116
122
  "Usage report not accepted by upstream backend. "
@@ -17,7 +17,7 @@ from zenml.constants import (
17
17
  ENV_ZENML_ACTIVE_STACK_ID,
18
18
  ENV_ZENML_ACTIVE_WORKSPACE_ID,
19
19
  )
20
- from zenml.enums import StackComponentType, StoreType
20
+ from zenml.enums import ExecutionStatus, StackComponentType, StoreType
21
21
  from zenml.integrations.utils import get_integration_for_module
22
22
  from zenml.models import (
23
23
  CodeReferenceRequest,
@@ -26,6 +26,7 @@ from zenml.models import (
26
26
  PipelineDeploymentRequest,
27
27
  PipelineDeploymentResponse,
28
28
  PipelineRunResponse,
29
+ PipelineRunUpdate,
29
30
  StackResponse,
30
31
  )
31
32
  from zenml.new.pipelines.run_utils import (
@@ -88,8 +89,6 @@ def run_pipeline(
88
89
  ensure_async_orchestrator(deployment=deployment_request, stack=stack)
89
90
 
90
91
  new_deployment = zen_store().create_deployment(deployment_request)
91
- placeholder_run = create_placeholder_run(deployment=new_deployment)
92
- assert placeholder_run
93
92
 
94
93
  if auth_context.access_token:
95
94
  token = auth_context.access_token
@@ -125,52 +124,62 @@ def run_pipeline(
125
124
  deployment_id=new_deployment.id
126
125
  )
127
126
 
128
- def _task() -> None:
129
- pypi_requirements, apt_packages = get_requirements_for_stack(
130
- stack=stack
131
- )
127
+ placeholder_run = create_placeholder_run(deployment=new_deployment)
128
+ assert placeholder_run
132
129
 
133
- if build.python_version:
134
- version_info = version.parse(build.python_version)
135
- python_version = f"{version_info.major}.{version_info.minor}"
136
- else:
137
- python_version = (
138
- f"{sys.version_info.major}.{sys.version_info.minor}"
130
+ def _task() -> None:
131
+ try:
132
+ pypi_requirements, apt_packages = get_requirements_for_stack(
133
+ stack=stack
139
134
  )
140
135
 
141
- dockerfile = generate_dockerfile(
142
- pypi_requirements=pypi_requirements,
143
- apt_packages=apt_packages,
144
- zenml_version=zenml_version,
145
- python_version=python_version,
146
- )
136
+ if build.python_version:
137
+ version_info = version.parse(build.python_version)
138
+ python_version = f"{version_info.major}.{version_info.minor}"
139
+ else:
140
+ python_version = (
141
+ f"{sys.version_info.major}.{sys.version_info.minor}"
142
+ )
143
+
144
+ dockerfile = generate_dockerfile(
145
+ pypi_requirements=pypi_requirements,
146
+ apt_packages=apt_packages,
147
+ zenml_version=zenml_version,
148
+ python_version=python_version,
149
+ )
147
150
 
148
- image_hash = generate_image_hash(dockerfile=dockerfile)
151
+ image_hash = generate_image_hash(dockerfile=dockerfile)
149
152
 
150
- runner_image = workload_manager().build_and_push_image(
151
- workload_id=new_deployment.id,
152
- dockerfile=dockerfile,
153
- image_name=f"{RUNNER_IMAGE_REPOSITORY}:{image_hash}",
154
- sync=True,
155
- )
153
+ runner_image = workload_manager().build_and_push_image(
154
+ workload_id=new_deployment.id,
155
+ dockerfile=dockerfile,
156
+ image_name=f"{RUNNER_IMAGE_REPOSITORY}:{image_hash}",
157
+ sync=True,
158
+ )
156
159
 
157
- workload_manager().log(
158
- workload_id=new_deployment.id,
159
- message="Starting pipeline deployment.",
160
- )
161
- workload_manager().run(
162
- workload_id=new_deployment.id,
163
- image=runner_image,
164
- command=command,
165
- arguments=args,
166
- environment=environment,
167
- timeout_in_seconds=30,
168
- sync=True,
169
- )
170
- workload_manager().log(
171
- workload_id=new_deployment.id,
172
- message="Pipeline deployed successfully.",
173
- )
160
+ workload_manager().log(
161
+ workload_id=new_deployment.id,
162
+ message="Starting pipeline deployment.",
163
+ )
164
+ workload_manager().run(
165
+ workload_id=new_deployment.id,
166
+ image=runner_image,
167
+ command=command,
168
+ arguments=args,
169
+ environment=environment,
170
+ timeout_in_seconds=30,
171
+ sync=True,
172
+ )
173
+ workload_manager().log(
174
+ workload_id=new_deployment.id,
175
+ message="Pipeline deployed successfully.",
176
+ )
177
+ except Exception:
178
+ zen_store().update_run(
179
+ run_id=placeholder_run.id,
180
+ run_update=PipelineRunUpdate(status=ExecutionStatus.FAILED),
181
+ )
182
+ raise
174
183
 
175
184
  if background_tasks:
176
185
  background_tasks.add_task(_task)
@@ -357,8 +366,12 @@ def apply_run_config(
357
366
  step_config = StepConfiguration.model_validate(step_config_dict)
358
367
 
359
368
  if update := run_config.steps.get(invocation_id):
369
+ update_dict = update.model_dump()
370
+ # Get rid of deprecated name to prevent overriding the step name
371
+ # with `None`.
372
+ update_dict.pop("name", None)
360
373
  step_config = pydantic_utils.update_model(
361
- step_config, update=update
374
+ step_config, update=update_dict
362
375
  )
363
376
  steps[invocation_id] = Step(spec=step.spec, config=step_config)
364
377
 
@@ -46,6 +46,7 @@ class Action(StrEnum):
46
46
  class ResourceType(StrEnum):
47
47
  """Resource types of the server API."""
48
48
 
49
+ ACTION = "action"
49
50
  ARTIFACT = "artifact"
50
51
  ARTIFACT_VERSION = "artifact_version"
51
52
  CODE_REPOSITORY = "code_repository"
@@ -189,7 +189,12 @@ def get_permission_denied_model(model: AnyResponse) -> AnyResponse:
189
189
  The permission denied model.
190
190
  """
191
191
  return model.model_copy(
192
- update={"body": None, "metadata": None, "permission_denied": True}
192
+ update={
193
+ "body": None,
194
+ "metadata": None,
195
+ "resources": None,
196
+ "permission_denied": True,
197
+ }
193
198
  )
194
199
 
195
200
 
@@ -384,10 +389,12 @@ def get_resource_type_for_model(
384
389
  is not associated with any resource type.
385
390
  """
386
391
  from zenml.models import (
392
+ ActionResponse,
387
393
  ArtifactResponse,
388
394
  ArtifactVersionResponse,
389
395
  CodeRepositoryResponse,
390
396
  ComponentResponse,
397
+ EventSourceResponse,
391
398
  FlavorResponse,
392
399
  ModelResponse,
393
400
  ModelVersionResponse,
@@ -402,6 +409,8 @@ def get_resource_type_for_model(
402
409
  ServiceResponse,
403
410
  StackResponse,
404
411
  TagResponse,
412
+ TriggerExecutionResponse,
413
+ TriggerResponse,
405
414
  UserResponse,
406
415
  WorkspaceResponse,
407
416
  )
@@ -410,6 +419,8 @@ def get_resource_type_for_model(
410
419
  Any,
411
420
  ResourceType,
412
421
  ] = {
422
+ ActionResponse: ResourceType.ACTION,
423
+ EventSourceResponse: ResourceType.EVENT_SOURCE,
413
424
  FlavorResponse: ResourceType.FLAVOR,
414
425
  ServiceConnectorResponse: ResourceType.SERVICE_CONNECTOR,
415
426
  ComponentResponse: ResourceType.STACK_COMPONENT,
@@ -428,6 +439,8 @@ def get_resource_type_for_model(
428
439
  PipelineBuildResponse: ResourceType.PIPELINE_BUILD,
429
440
  PipelineRunResponse: ResourceType.PIPELINE_RUN,
430
441
  TagResponse: ResourceType.TAG,
442
+ TriggerResponse: ResourceType.TRIGGER,
443
+ TriggerExecutionResponse: ResourceType.TRIGGER_EXECUTION,
431
444
  ServiceAccountResponse: ResourceType.SERVICE_ACCOUNT,
432
445
  ServiceResponse: ResourceType.SERVICE,
433
446
  }
@@ -522,9 +535,11 @@ def get_schema_for_resource_type(
522
535
  The database schema.
523
536
  """
524
537
  from zenml.zen_stores.schemas import (
538
+ ActionSchema,
525
539
  ArtifactSchema,
526
540
  ArtifactVersionSchema,
527
541
  CodeRepositorySchema,
542
+ EventSourceSchema,
528
543
  FlavorSchema,
529
544
  ModelSchema,
530
545
  ModelVersionSchema,
@@ -539,6 +554,8 @@ def get_schema_for_resource_type(
539
554
  StackComponentSchema,
540
555
  StackSchema,
541
556
  TagSchema,
557
+ TriggerExecutionSchema,
558
+ TriggerSchema,
542
559
  UserSchema,
543
560
  WorkspaceSchema,
544
561
  )
@@ -564,6 +581,10 @@ def get_schema_for_resource_type(
564
581
  ResourceType.PIPELINE_BUILD: PipelineBuildSchema,
565
582
  ResourceType.RUN_METADATA: RunMetadataSchema,
566
583
  ResourceType.USER: UserSchema,
584
+ ResourceType.ACTION: ActionSchema,
585
+ ResourceType.EVENT_SOURCE: EventSourceSchema,
586
+ ResourceType.TRIGGER: TriggerSchema,
587
+ ResourceType.TRIGGER_EXECUTION: TriggerExecutionSchema,
567
588
  }
568
589
 
569
590
  return mapping[resource_type]
@@ -15,7 +15,7 @@
15
15
 
16
16
  from typing import TYPE_CHECKING, Dict, List, Set, Tuple
17
17
 
18
- from zenml.zen_server.cloud_utils import ZenMLCloudSession
18
+ from zenml.zen_server.cloud_utils import cloud_connection
19
19
  from zenml.zen_server.rbac.models import Action, Resource
20
20
  from zenml.zen_server.rbac.rbac_interface import RBACInterface
21
21
  from zenml.zen_server.utils import server_config
@@ -74,9 +74,13 @@ def _convert_from_cloud_resource(cloud_resource: str) -> Resource:
74
74
  return Resource(type=resource_type_and_id)
75
75
 
76
76
 
77
- class ZenMLCloudRBAC(RBACInterface, ZenMLCloudSession):
77
+ class ZenMLCloudRBAC(RBACInterface):
78
78
  """RBAC implementation that uses the ZenML Pro Management Plane as a backend."""
79
79
 
80
+ def __init__(self) -> None:
81
+ """Initialize the object."""
82
+ self._connection = cloud_connection()
83
+
80
84
  def check_permissions(
81
85
  self, user: "UserResponse", resources: Set[Resource], action: Action
82
86
  ) -> Dict[Resource, bool]:
@@ -110,7 +114,9 @@ class ZenMLCloudRBAC(RBACInterface, ZenMLCloudSession):
110
114
  ],
111
115
  "action": str(action),
112
116
  }
113
- response = self._get(endpoint=PERMISSIONS_ENDPOINT, params=params)
117
+ response = self._connection.get(
118
+ endpoint=PERMISSIONS_ENDPOINT, params=params
119
+ )
114
120
  value = response.json()
115
121
 
116
122
  assert isinstance(value, dict)
@@ -147,7 +153,7 @@ class ZenMLCloudRBAC(RBACInterface, ZenMLCloudSession):
147
153
  "resource": _convert_to_cloud_resource(resource),
148
154
  "action": str(action),
149
155
  }
150
- response = self._get(
156
+ response = self._connection.get(
151
157
  endpoint=ALLOWED_RESOURCE_IDS_ENDPOINT, params=params
152
158
  )
153
159
  response_json = response.json()
@@ -177,4 +183,4 @@ class ZenMLCloudRBAC(RBACInterface, ZenMLCloudSession):
177
183
  "resource": _convert_to_cloud_resource(resource),
178
184
  "actions": [str(action) for action in actions],
179
185
  }
180
- self._post(endpoint=RESOURCE_MEMBERSHIP_ENDPOINT, data=data)
186
+ self._connection.post(endpoint=RESOURCE_MEMBERSHIP_ENDPOINT, data=data)
@@ -0,0 +1,324 @@
1
+ # Copyright (c) ZenML GmbH 2024. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at:
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12
+ # or implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+ """Endpoint definitions for actions."""
15
+
16
+ from uuid import UUID
17
+
18
+ from fastapi import APIRouter, Depends, Security
19
+
20
+ from zenml import ActionRequest
21
+ from zenml.actions.base_action import BaseActionHandler
22
+ from zenml.constants import (
23
+ ACTIONS,
24
+ API,
25
+ VERSION_1,
26
+ )
27
+ from zenml.enums import PluginType
28
+ from zenml.models import (
29
+ ActionFilter,
30
+ ActionResponse,
31
+ ActionUpdate,
32
+ Page,
33
+ )
34
+ from zenml.zen_server.auth import AuthContext, authorize
35
+ from zenml.zen_server.exceptions import error_response
36
+ from zenml.zen_server.rbac.endpoint_utils import (
37
+ verify_permissions_and_create_entity,
38
+ verify_permissions_and_list_entities,
39
+ )
40
+ from zenml.zen_server.rbac.models import Action, ResourceType
41
+ from zenml.zen_server.rbac.utils import (
42
+ dehydrate_response_model,
43
+ verify_permission_for_model,
44
+ )
45
+ from zenml.zen_server.utils import (
46
+ handle_exceptions,
47
+ make_dependable,
48
+ plugin_flavor_registry,
49
+ zen_store,
50
+ )
51
+
52
+ router = APIRouter(
53
+ prefix=API + VERSION_1 + ACTIONS,
54
+ tags=["actions"],
55
+ responses={401: error_response, 403: error_response},
56
+ )
57
+
58
+
59
+ @router.get(
60
+ "",
61
+ response_model=Page[ActionResponse],
62
+ responses={401: error_response, 404: error_response, 422: error_response},
63
+ )
64
+ @handle_exceptions
65
+ def list_actions(
66
+ action_filter_model: ActionFilter = Depends(make_dependable(ActionFilter)),
67
+ hydrate: bool = False,
68
+ _: AuthContext = Security(authorize),
69
+ ) -> Page[ActionResponse]:
70
+ """List actions.
71
+
72
+ Args:
73
+ action_filter_model: Filter model used for pagination, sorting,
74
+ filtering.
75
+ hydrate: Flag deciding whether to hydrate the output model(s)
76
+ by including metadata fields in the response.
77
+
78
+ Returns:
79
+ Page of actions.
80
+ """
81
+
82
+ def list_actions_fn(
83
+ filter_model: ActionFilter,
84
+ ) -> Page[ActionResponse]:
85
+ """List actions through their associated plugins.
86
+
87
+ Args:
88
+ filter_model: Filter model used for pagination, sorting,
89
+ filtering.
90
+
91
+ Raises:
92
+ ValueError: If the action handler for flavor/type is not valid.
93
+
94
+ Returns:
95
+ All actions.
96
+ """
97
+ actions = zen_store().list_actions(
98
+ action_filter_model=filter_model, hydrate=hydrate
99
+ )
100
+
101
+ # Process the actions through their associated plugins
102
+ for idx, action in enumerate(actions.items):
103
+ action_handler = plugin_flavor_registry().get_plugin(
104
+ name=action.flavor,
105
+ _type=PluginType.ACTION,
106
+ subtype=action.plugin_subtype,
107
+ )
108
+
109
+ # Validate that the flavor and plugin_type correspond to an action
110
+ # handler implementation
111
+ if not isinstance(action_handler, BaseActionHandler):
112
+ raise ValueError(
113
+ f"Action handler plugin {action.plugin_subtype} "
114
+ f"for flavor {action.flavor} is not a valid action "
115
+ "handler plugin."
116
+ )
117
+
118
+ actions.items[idx] = action_handler.get_action(
119
+ action, hydrate=hydrate
120
+ )
121
+
122
+ return actions
123
+
124
+ return verify_permissions_and_list_entities(
125
+ filter_model=action_filter_model,
126
+ resource_type=ResourceType.ACTION,
127
+ list_method=list_actions_fn,
128
+ )
129
+
130
+
131
+ @router.get(
132
+ "/{action_id}",
133
+ response_model=ActionResponse,
134
+ responses={401: error_response, 404: error_response, 422: error_response},
135
+ )
136
+ @handle_exceptions
137
+ def get_action(
138
+ action_id: UUID,
139
+ hydrate: bool = True,
140
+ _: AuthContext = Security(authorize),
141
+ ) -> ActionResponse:
142
+ """Returns the requested action.
143
+
144
+ Args:
145
+ action_id: ID of the action.
146
+ hydrate: Flag deciding whether to hydrate the output model(s)
147
+ by including metadata fields in the response.
148
+
149
+ Raises:
150
+ ValueError: If the action handler for flavor/type is not valid.
151
+
152
+ Returns:
153
+ The requested action.
154
+ """
155
+ action = zen_store().get_action(action_id=action_id, hydrate=hydrate)
156
+
157
+ verify_permission_for_model(action, action=Action.READ)
158
+
159
+ action_handler = plugin_flavor_registry().get_plugin(
160
+ name=action.flavor,
161
+ _type=PluginType.ACTION,
162
+ subtype=action.plugin_subtype,
163
+ )
164
+
165
+ # Validate that the flavor and plugin_type correspond to an action
166
+ # handler implementation
167
+ if not isinstance(action_handler, BaseActionHandler):
168
+ raise ValueError(
169
+ f"Action handler plugin {action.plugin_subtype} "
170
+ f"for flavor {action.flavor} is not a valid action "
171
+ "handler plugin."
172
+ )
173
+
174
+ action = action_handler.get_action(action, hydrate=hydrate)
175
+
176
+ return dehydrate_response_model(action)
177
+
178
+
179
+ @router.post(
180
+ "",
181
+ response_model=ActionResponse,
182
+ responses={401: error_response, 409: error_response, 422: error_response},
183
+ )
184
+ @handle_exceptions
185
+ def create_action(
186
+ action: ActionRequest,
187
+ _: AuthContext = Security(authorize),
188
+ ) -> ActionResponse:
189
+ """Creates an action.
190
+
191
+ Args:
192
+ action: Action to create.
193
+
194
+ Raises:
195
+ ValueError: If the action handler for flavor/type is not valid.
196
+
197
+ Returns:
198
+ The created action.
199
+ """
200
+ service_account = zen_store().get_service_account(
201
+ service_account_name_or_id=action.service_account_id
202
+ )
203
+ verify_permission_for_model(service_account, action=Action.READ)
204
+
205
+ action_handler = plugin_flavor_registry().get_plugin(
206
+ name=action.flavor,
207
+ _type=PluginType.ACTION,
208
+ subtype=action.plugin_subtype,
209
+ )
210
+
211
+ # Validate that the flavor and plugin_type correspond to an action
212
+ # handler implementation
213
+ if not isinstance(action_handler, BaseActionHandler):
214
+ raise ValueError(
215
+ f"Action handler plugin {action.plugin_subtype} "
216
+ f"for flavor {action.flavor} is not a valid action "
217
+ "handler plugin."
218
+ )
219
+
220
+ return verify_permissions_and_create_entity(
221
+ request_model=action,
222
+ resource_type=ResourceType.ACTION,
223
+ create_method=action_handler.create_action,
224
+ )
225
+
226
+
227
+ @router.put(
228
+ "/{action_id}",
229
+ response_model=ActionResponse,
230
+ responses={401: error_response, 404: error_response, 422: error_response},
231
+ )
232
+ @handle_exceptions
233
+ def update_action(
234
+ action_id: UUID,
235
+ action_update: ActionUpdate,
236
+ _: AuthContext = Security(authorize),
237
+ ) -> ActionResponse:
238
+ """Update an action.
239
+
240
+ Args:
241
+ action_id: ID of the action to update.
242
+ action_update: The action update.
243
+
244
+ Raises:
245
+ ValueError: If the action handler for flavor/type is not valid.
246
+
247
+ Returns:
248
+ The updated action.
249
+ """
250
+ action = zen_store().get_action(action_id=action_id)
251
+
252
+ verify_permission_for_model(action, action=Action.UPDATE)
253
+
254
+ if action_update.service_account_id:
255
+ service_account = zen_store().get_service_account(
256
+ service_account_name_or_id=action_update.service_account_id
257
+ )
258
+ verify_permission_for_model(service_account, action=Action.READ)
259
+
260
+ action_handler = plugin_flavor_registry().get_plugin(
261
+ name=action.flavor,
262
+ _type=PluginType.ACTION,
263
+ subtype=action.plugin_subtype,
264
+ )
265
+
266
+ # Validate that the flavor and plugin_type correspond to an action
267
+ # handler implementation
268
+ if not isinstance(action_handler, BaseActionHandler):
269
+ raise ValueError(
270
+ f"Action handler plugin {action.plugin_subtype} "
271
+ f"for flavor {action.flavor} is not a valid action "
272
+ "handler plugin."
273
+ )
274
+
275
+ updated_action = action_handler.update_action(
276
+ action=action,
277
+ action_update=action_update,
278
+ )
279
+
280
+ return dehydrate_response_model(updated_action)
281
+
282
+
283
+ @router.delete(
284
+ "/{action_id}",
285
+ responses={401: error_response, 404: error_response, 422: error_response},
286
+ )
287
+ @handle_exceptions
288
+ def delete_action(
289
+ action_id: UUID,
290
+ force: bool = False,
291
+ _: AuthContext = Security(authorize),
292
+ ) -> None:
293
+ """Delete an action.
294
+
295
+ Args:
296
+ action_id: ID of the action.
297
+ force: Flag deciding whether to force delete the action.
298
+
299
+ Raises:
300
+ ValueError: If the action handler for flavor/type is not valid.
301
+ """
302
+ action = zen_store().get_action(action_id=action_id)
303
+
304
+ verify_permission_for_model(action, action=Action.DELETE)
305
+
306
+ action_handler = plugin_flavor_registry().get_plugin(
307
+ name=action.flavor,
308
+ _type=PluginType.ACTION,
309
+ subtype=action.plugin_subtype,
310
+ )
311
+
312
+ # Validate that the flavor and plugin_type correspond to an action
313
+ # handler implementation
314
+ if not isinstance(action_handler, BaseActionHandler):
315
+ raise ValueError(
316
+ f"Action handler plugin {action.plugin_subtype} "
317
+ f"for flavor {action.flavor} is not a valid action "
318
+ "handler plugin."
319
+ )
320
+
321
+ action_handler.delete_action(
322
+ action=action,
323
+ force=force,
324
+ )