zenml-nightly 0.83.0.dev20250623__py3-none-any.whl → 0.83.1.dev20250625__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 (158) hide show
  1. zenml/VERSION +1 -1
  2. zenml/cli/login.py +21 -3
  3. zenml/config/__init__.py +13 -2
  4. zenml/constants.py +0 -1
  5. zenml/exceptions.py +16 -0
  6. zenml/integrations/airflow/orchestrators/airflow_orchestrator.py +15 -6
  7. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +54 -58
  8. zenml/integrations/azure/orchestrators/azureml_orchestrator.py +28 -19
  9. zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +19 -63
  10. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +36 -61
  11. zenml/integrations/hyperai/orchestrators/hyperai_orchestrator.py +19 -22
  12. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +28 -31
  13. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +33 -20
  14. zenml/integrations/lightning/orchestrators/lightning_orchestrator.py +25 -100
  15. zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +19 -8
  16. zenml/integrations/skypilot/utils.py +17 -13
  17. zenml/integrations/tekton/orchestrators/tekton_orchestrator.py +28 -12
  18. zenml/models/v2/core/step_run.py +1 -0
  19. zenml/orchestrators/__init__.py +2 -0
  20. zenml/orchestrators/base_orchestrator.py +137 -66
  21. zenml/orchestrators/input_utils.py +5 -13
  22. zenml/orchestrators/local/local_orchestrator.py +19 -9
  23. zenml/orchestrators/local_docker/local_docker_orchestrator.py +15 -5
  24. zenml/orchestrators/publish_utils.py +24 -0
  25. zenml/orchestrators/step_run_utils.py +1 -2
  26. zenml/pipelines/run_utils.py +12 -7
  27. zenml/step_operators/step_operator_entrypoint_configuration.py +1 -1
  28. zenml/zen_server/dashboard/assets/{404-DmJUgorp.js → 404-B5eko6XL.js} +1 -1
  29. zenml/zen_server/dashboard/assets/{@reactflow-8OCk19Fi.js → @reactflow-B_iCtR7X.js} +1 -1
  30. zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-CZW4QyWn.js → AlertDialogDropdownItem-DsOmO1FH.js} +1 -1
  31. zenml/zen_server/dashboard/assets/{ButtonGroup-DFWWFGUE.js → ButtonGroup-4sPZDv70.js} +1 -1
  32. zenml/zen_server/dashboard/assets/{CodeSnippet-D2HkkAGr.js → CodeSnippet-Ctplhzdc.js} +1 -1
  33. zenml/zen_server/dashboard/assets/{CollapsibleCard-CnS09ljw.js → CollapsibleCard-CBKenz9f.js} +1 -1
  34. zenml/zen_server/dashboard/assets/{ComponentBadge-CDgdd0Ks.js → ComponentBadge-Cnecw3qz.js} +1 -1
  35. zenml/zen_server/dashboard/assets/{ComponentIcon-CbbOc7lb.js → ComponentIcon-CMiVW-O6.js} +1 -1
  36. zenml/zen_server/dashboard/assets/{DeleteAlertDialog-VIOMDLmx.js → DeleteAlertDialog-DEI0YDzP.js} +1 -1
  37. zenml/zen_server/dashboard/assets/{DialogItem-ClFCqxEp.js → DialogItem-CRCDpYU6.js} +1 -1
  38. zenml/zen_server/dashboard/assets/{Error-CQzjbDcN.js → Error-BG6f_WRd.js} +1 -1
  39. zenml/zen_server/dashboard/assets/{ExecutionStatus-CWreILP0.js → ExecutionStatus-BuhNAE9w.js} +1 -1
  40. zenml/zen_server/dashboard/assets/{Helpbox-CiKxG5_X.js → Helpbox-DtUG2Bf_.js} +1 -1
  41. zenml/zen_server/dashboard/assets/{Infobox-CGxFvqzi.js → Infobox-CSBRrM6r.js} +1 -1
  42. zenml/zen_server/dashboard/assets/{LeftSideMenu-DCsKdIjC.js → LeftSideMenu-DPsCCK3z.js} +1 -1
  43. zenml/zen_server/dashboard/assets/{NestedCollapsible-3M4llYtH.js → NestedCollapsible-CMuDIJlp.js} +1 -1
  44. zenml/zen_server/dashboard/assets/{NumberBox-C0mQktmV.js → NumberBox-DtCv7jh3.js} +1 -1
  45. zenml/zen_server/dashboard/assets/Pagination-CWnEpSpN.js +1 -0
  46. zenml/zen_server/dashboard/assets/{Partials-DSjkttlz.js → Partials-CfHD6OH5.js} +1 -1
  47. zenml/zen_server/dashboard/assets/{ProCta-Dm5cWKpS.js → ProCta-CNyp04C8.js} +1 -1
  48. zenml/zen_server/dashboard/assets/{ProviderIcon-DPwMR6nF.js → ProviderIcon-DHejyg7C.js} +1 -1
  49. zenml/zen_server/dashboard/assets/{ProviderRadio-DEDNRgAb.js → ProviderRadio-tGtie8Gc.js} +1 -1
  50. zenml/zen_server/dashboard/assets/RunsBody-mYwMcWWj.js +1 -0
  51. zenml/zen_server/dashboard/assets/SearchField-BtUi6cYl.js +1 -0
  52. zenml/zen_server/dashboard/assets/{SecretTooltip-CZTRnaCV.js → SecretTooltip-B5u1UsQ9.js} +1 -1
  53. zenml/zen_server/dashboard/assets/{SetPassword-BjNGDC5e.js → SetPassword-BmbgL_ed.js} +1 -1
  54. zenml/zen_server/dashboard/assets/{SheetHeader-CASpN2Lz.js → SheetHeader-DkH7aG9K.js} +1 -1
  55. zenml/zen_server/dashboard/assets/StackComponentList-Bi8BKqCu.js +1 -0
  56. zenml/zen_server/dashboard/assets/StackList-Cvxapo0p.js +1 -0
  57. zenml/zen_server/dashboard/assets/{StackName-ojLC6xdl.js → StackName-CFSZL8ec.js} +1 -1
  58. zenml/zen_server/dashboard/assets/Tabs-D4dv48ry.js +1 -0
  59. zenml/zen_server/dashboard/assets/{Tick-BPrWnNlN.js → Tick-Qquvr4P3.js} +1 -1
  60. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-CNfKDo2Q.js → UpdatePasswordSchemas-D_DCETSO.js} +1 -1
  61. zenml/zen_server/dashboard/assets/{UsageReason-Cb-mpV8M.js → UsageReason-DhiUV1bu.js} +1 -1
  62. zenml/zen_server/dashboard/assets/{Wizard-Dg8Pmn5A.js → Wizard-BHvY75u_.js} +1 -1
  63. zenml/zen_server/dashboard/assets/{WizardFooter-BcNDIvlQ.js → WizardFooter-FQm8y-jP.js} +1 -1
  64. zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-DCdax7I5.js → all-pipeline-runs-query-DpKw9WL9.js} +1 -1
  65. zenml/zen_server/dashboard/assets/{bulk-delete-C_kpIB9A.js → bulk-delete-CzYA--cC.js} +1 -1
  66. zenml/zen_server/dashboard/assets/{configuration-form-B2hmKGnF.js → configuration-form-DSoMMiPE.js} +1 -1
  67. zenml/zen_server/dashboard/assets/{constants-1EZZxtay.js → constants-DTfsIqHy.js} +1 -1
  68. zenml/zen_server/dashboard/assets/{create-stack-TKmMtrkQ.js → create-stack-BpZrmKDu.js} +1 -1
  69. zenml/zen_server/dashboard/assets/{delete-run-CCR9md_s.js → delete-run-BkyDsKQc.js} +1 -1
  70. zenml/zen_server/dashboard/assets/elk-worker.min-BdOC9sib.js +6263 -0
  71. zenml/zen_server/dashboard/assets/expand-full-BPiXpch2.js +1 -0
  72. zenml/zen_server/dashboard/assets/{form-DFJkaFDX.js → form-BgtamtJm.js} +1 -1
  73. zenml/zen_server/dashboard/assets/{form-schemas-CrznJVzA.js → form-schemas-dyDkAxXP.js} +1 -1
  74. zenml/zen_server/dashboard/assets/{index-BjUu1mP4.js → index-BBt0LDtR.js} +1 -1
  75. zenml/zen_server/dashboard/assets/index-BfNISy0X.css +1 -0
  76. zenml/zen_server/dashboard/assets/{index-BFqbGSck.js → index-BgEfQ3_G.js} +4 -4
  77. zenml/zen_server/dashboard/assets/{index-U992soPJ.js → index-eoDB_1XX.js} +1 -1
  78. zenml/zen_server/dashboard/assets/{layout-Do9YI4QX.js → layout-o1x87a3q.js} +1 -1
  79. zenml/zen_server/dashboard/assets/{login-mutation-D3tFP6Wm.js → login-mutation-C1hvP_cX.js} +1 -1
  80. zenml/zen_server/dashboard/assets/page-4xUZpMN0.js +31 -0
  81. zenml/zen_server/dashboard/assets/page-4zc4xPv2.js +2 -0
  82. zenml/zen_server/dashboard/assets/page-B0104V6C.js +1 -0
  83. zenml/zen_server/dashboard/assets/page-BNJsjvof.js +1 -0
  84. zenml/zen_server/dashboard/assets/{page-sJjNT9xA.js → page-BPQ66vR-.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{page-CAJ8B0vb.js → page-BQgSZ2nH.js} +1 -1
  86. zenml/zen_server/dashboard/assets/page-BXl2ZX6J.js +1 -0
  87. zenml/zen_server/dashboard/assets/{page-CtiuMP_r.js → page-BxeZrG_t.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{page-Cal6XQ4U.js → page-C2A-2Cj_.js} +1 -1
  89. zenml/zen_server/dashboard/assets/page-C2i-C7jv.js +1 -0
  90. zenml/zen_server/dashboard/assets/{page-DJIGaUQ9.js → page-C3JfJxuR.js} +1 -1
  91. zenml/zen_server/dashboard/assets/{page-ChGcZI_6.js → page-CESEqC2L.js} +1 -1
  92. zenml/zen_server/dashboard/assets/{page-DCcuPZ8P.js → page-CF8cTZ7l.js} +1 -1
  93. zenml/zen_server/dashboard/assets/page-CKjsimVu.js +1 -0
  94. zenml/zen_server/dashboard/assets/{page-DNjKHjnH.js → page-COLzBwff.js} +1 -1
  95. zenml/zen_server/dashboard/assets/page-COifg5fa.js +1 -0
  96. zenml/zen_server/dashboard/assets/{page-CnbIYE80.js → page-CQeJuA8T.js} +1 -1
  97. zenml/zen_server/dashboard/assets/{page-DKK6ulgy.js → page-CcjWEjre.js} +1 -1
  98. zenml/zen_server/dashboard/assets/{page-9RjCitFH.js → page-CefGLeWy.js} +1 -1
  99. zenml/zen_server/dashboard/assets/{page-DUKbOhaD.js → page-CfxpV3j4.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{page-D9Hfx6GV.js → page-ClcUzawe.js} +1 -1
  101. zenml/zen_server/dashboard/assets/page-Ct_LB3zo.js +1 -0
  102. zenml/zen_server/dashboard/assets/page-D-ZWUMYY.js +1 -0
  103. zenml/zen_server/dashboard/assets/{page-CUaMMoPG.js → page-D-tJ_Y0a.js} +1 -1
  104. zenml/zen_server/dashboard/assets/{page-CdZCmszX.js → page-DHrvih9u.js} +1 -1
  105. zenml/zen_server/dashboard/assets/{page-DUK0Nd_1.js → page-DMhaHZDw.js} +1 -1
  106. zenml/zen_server/dashboard/assets/{page-CAUYrfui.js → page-DOCOmmKn.js} +1 -1
  107. zenml/zen_server/dashboard/assets/{page-akLcPcKw.js → page-DcQmxKLp.js} +1 -1
  108. zenml/zen_server/dashboard/assets/page-Dh4GRWw5.js +1 -0
  109. zenml/zen_server/dashboard/assets/{page-DwVPpCFg.js → page-DiHZK-1w.js} +1 -1
  110. zenml/zen_server/dashboard/assets/page-Dn7ZNapg.js +1 -0
  111. zenml/zen_server/dashboard/assets/page-Dy4vSQY7.js +1 -0
  112. zenml/zen_server/dashboard/assets/{page-CN7lkvXr.js → page-QrvWQwZb.js} +1 -1
  113. zenml/zen_server/dashboard/assets/{page-BrT0_zSJ.js → page-RF3Fup0q.js} +1 -1
  114. zenml/zen_server/dashboard/assets/page-WuvCrN47.js +1 -0
  115. zenml/zen_server/dashboard/assets/{page-Be3R2uYn.js → page-_WnHBI1F.js} +1 -1
  116. zenml/zen_server/dashboard/assets/{page-C210HcBA.js → page-ghjVNgVE.js} +1 -1
  117. zenml/zen_server/dashboard/assets/{page-BCrKmYIZ.js → page-iDsDiDXw.js} +1 -1
  118. zenml/zen_server/dashboard/assets/{page-ClvmVesa.js → page-rVhXI5ZO.js} +1 -1
  119. zenml/zen_server/dashboard/assets/{page-DEohTSz6.js → page-uxjMX8Iq.js} +1 -1
  120. zenml/zen_server/dashboard/assets/{persist-Dec_w7aB.js → persist-BsdEtCkd.js} +1 -1
  121. zenml/zen_server/dashboard/assets/{persist-DWMWVP-y.js → persist-CFPbMcJX.js} +1 -1
  122. zenml/zen_server/dashboard/assets/{resource-tyes-list-o2LXiMay.js → resource-tyes-list-79FqS3LY.js} +1 -1
  123. zenml/zen_server/dashboard/assets/{resource-type-tooltip-DwHrJstL.js → resource-type-tooltip-BL9ZTRKi.js} +1 -1
  124. zenml/zen_server/dashboard/assets/{service-connectors-DSEMwJ5A.js → service-connectors-Q8h7-_rG.js} +1 -1
  125. zenml/zen_server/dashboard/assets/{service-jxtvgks0.js → service-k-9Vsb30.js} +1 -1
  126. zenml/zen_server/dashboard/assets/{sharedSchema-BXzg0EZz.js → sharedSchema-C_HkejsG.js} +1 -1
  127. zenml/zen_server/dashboard/assets/{stack-detail-query-Cm0fsgo-.js → stack-detail-query-CNmVZ0Bo.js} +1 -1
  128. zenml/zen_server/dashboard/assets/{update-current-user-mutation-D5MjcQ6F.js → update-current-user-mutation-Ca-Lmwuj.js} +1 -1
  129. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-CmnxdxiK.js → update-server-settings-mutation-Bwe3gUt4.js} +1 -1
  130. zenml/zen_server/dashboard/index.html +4 -4
  131. zenml/zen_stores/migrations/versions/0.83.1_release.py +23 -0
  132. zenml/zen_stores/rest_zen_store.py +147 -128
  133. zenml/zen_stores/sql_zen_store.py +27 -17
  134. {zenml_nightly-0.83.0.dev20250623.dist-info → zenml_nightly-0.83.1.dev20250625.dist-info}/METADATA +5 -9
  135. {zenml_nightly-0.83.0.dev20250623.dist-info → zenml_nightly-0.83.1.dev20250625.dist-info}/RECORD +138 -134
  136. zenml/zen_server/dashboard/assets/RunsBody-BRBn1e2O.js +0 -1
  137. zenml/zen_server/dashboard/assets/SearchField-DY6-UbRT.js +0 -1
  138. zenml/zen_server/dashboard/assets/StackComponentList-Be1pQt9m.js +0 -1
  139. zenml/zen_server/dashboard/assets/StackList-BdiR5DvR.js +0 -1
  140. zenml/zen_server/dashboard/assets/Tabs-DNSKblCM.js +0 -1
  141. zenml/zen_server/dashboard/assets/index-DuhuqTCI.css +0 -1
  142. zenml/zen_server/dashboard/assets/page-B0PsXWiT.js +0 -1
  143. zenml/zen_server/dashboard/assets/page-BcRI3-aR.js +0 -29
  144. zenml/zen_server/dashboard/assets/page-BgknnddT.js +0 -1
  145. zenml/zen_server/dashboard/assets/page-Bs3W2FDi.js +0 -1
  146. zenml/zen_server/dashboard/assets/page-C6KaiZ_W.js +0 -1
  147. zenml/zen_server/dashboard/assets/page-CHxVhF3x.js +0 -1
  148. zenml/zen_server/dashboard/assets/page-CktmtZ8Z.js +0 -1
  149. zenml/zen_server/dashboard/assets/page-CoXzjeEY.js +0 -1
  150. zenml/zen_server/dashboard/assets/page-D9iuB88h.js +0 -1
  151. zenml/zen_server/dashboard/assets/page-DYOucPtA.js +0 -1
  152. zenml/zen_server/dashboard/assets/page-DpqRelAy.js +0 -1
  153. zenml/zen_server/dashboard/assets/page-XURWnYZP.js +0 -1
  154. zenml/zen_server/dashboard/assets/page-abw-2oeW.js +0 -1
  155. zenml/zen_server/dashboard/assets/page-n9ejQ2V3.js +0 -2
  156. {zenml_nightly-0.83.0.dev20250623.dist-info → zenml_nightly-0.83.1.dev20250625.dist-info}/LICENSE +0 -0
  157. {zenml_nightly-0.83.0.dev20250623.dist-info → zenml_nightly-0.83.1.dev20250625.dist-info}/WHEEL +0 -0
  158. {zenml_nightly-0.83.0.dev20250623.dist-info → zenml_nightly-0.83.1.dev20250625.dist-info}/entry_points.txt +0 -0
@@ -33,7 +33,6 @@
33
33
  import os
34
34
  from typing import (
35
35
  TYPE_CHECKING,
36
- Any,
37
36
  Dict,
38
37
  List,
39
38
  Optional,
@@ -62,7 +61,7 @@ from zenml.integrations.kubernetes.orchestrators.manifest_utils import (
62
61
  )
63
62
  from zenml.integrations.kubernetes.pod_settings import KubernetesPodSettings
64
63
  from zenml.logger import get_logger
65
- from zenml.orchestrators import ContainerizedOrchestrator
64
+ from zenml.orchestrators import ContainerizedOrchestrator, SubmissionResult
66
65
  from zenml.orchestrators.utils import get_orchestrator_run_name
67
66
  from zenml.stack import StackValidator
68
67
 
@@ -388,24 +387,32 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
388
387
  """
389
388
  return f"zenml-token-{deployment_id}"
390
389
 
391
- def prepare_or_run_pipeline(
390
+ def submit_pipeline(
392
391
  self,
393
392
  deployment: "PipelineDeploymentResponse",
394
393
  stack: "Stack",
395
394
  environment: Dict[str, str],
396
395
  placeholder_run: Optional["PipelineRunResponse"] = None,
397
- ) -> Any:
398
- """Runs the pipeline in Kubernetes.
396
+ ) -> Optional[SubmissionResult]:
397
+ """Submits a pipeline to the orchestrator.
398
+
399
+ This method should only submit the pipeline and not wait for it to
400
+ complete. If the orchestrator is configured to wait for the pipeline run
401
+ to complete, a function that waits for the pipeline run to complete can
402
+ be passed as part of the submission result.
399
403
 
400
404
  Args:
401
- deployment: The pipeline deployment to prepare or run.
405
+ deployment: The pipeline deployment to submit.
402
406
  stack: The stack the pipeline will run on.
403
407
  environment: Environment variables to set in the orchestration
404
- environment.
408
+ environment. These don't need to be set if running locally.
405
409
  placeholder_run: An optional placeholder run for the deployment.
406
410
 
407
411
  Raises:
408
- RuntimeError: If the Kubernetes orchestrator is not configured.
412
+ RuntimeError: If a schedule without cron expression is given.
413
+
414
+ Returns:
415
+ Optional submission result.
409
416
  """
410
417
  for step_name, step in deployment.step_configurations.items():
411
418
  if self.requires_resources_in_orchestration_environment(step):
@@ -536,7 +543,7 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
536
543
  f"Scheduling Kubernetes run `{pod_name}` with CRON expression "
537
544
  f'`"{cron_expression}"`.'
538
545
  )
539
- return
546
+ return None
540
547
  else:
541
548
  # Create and run the orchestrator pod.
542
549
  pod_manifest = build_pod_manifest(
@@ -565,18 +572,23 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
565
572
  startup_timeout=settings.pod_startup_timeout,
566
573
  )
567
574
 
568
- # Wait for the orchestrator pod to finish and stream logs.
569
575
  if settings.synchronous:
570
- logger.info(
571
- "Waiting for Kubernetes orchestrator pod to finish..."
572
- )
573
- kube_utils.wait_pod(
574
- kube_client_fn=self.get_kube_client,
575
- pod_name=pod_name,
576
- namespace=self.config.kubernetes_namespace,
577
- exit_condition_lambda=kube_utils.pod_is_done,
578
- timeout_sec=settings.timeout,
579
- stream_logs=True,
576
+
577
+ def _wait_for_run_to_finish() -> None:
578
+ logger.info(
579
+ "Waiting for Kubernetes orchestrator pod to finish..."
580
+ )
581
+ kube_utils.wait_pod(
582
+ kube_client_fn=self.get_kube_client,
583
+ pod_name=pod_name,
584
+ namespace=self.config.kubernetes_namespace,
585
+ exit_condition_lambda=kube_utils.pod_is_done,
586
+ timeout_sec=settings.timeout,
587
+ stream_logs=True,
588
+ )
589
+
590
+ return SubmissionResult(
591
+ wait_for_completion=_wait_for_run_to_finish
580
592
  )
581
593
  else:
582
594
  logger.info(
@@ -585,6 +597,7 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
585
597
  f"Run the following command to inspect the logs: "
586
598
  f"`kubectl logs {pod_name} -n {self.config.kubernetes_namespace}`."
587
599
  )
600
+ return None
588
601
 
589
602
  def _get_service_account_name(
590
603
  self, settings: KubernetesOrchestratorSettings
@@ -16,14 +16,14 @@
16
16
  import os
17
17
  import tempfile
18
18
  import time
19
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, cast
19
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, cast
20
20
  from uuid import uuid4
21
21
 
22
22
  from lightning_sdk import Machine, Studio
23
23
 
24
+ from zenml import __version__
24
25
  from zenml.constants import (
25
26
  ENV_ZENML_CUSTOM_SOURCE_ROOT,
26
- ENV_ZENML_WHEEL_PACKAGE_NAME,
27
27
  )
28
28
  from zenml.entrypoints.step_entrypoint_configuration import (
29
29
  StepEntrypointConfiguration,
@@ -40,9 +40,8 @@ from zenml.integrations.lightning.orchestrators.utils import (
40
40
  sanitize_studio_name,
41
41
  )
42
42
  from zenml.logger import get_logger
43
+ from zenml.orchestrators import BaseOrchestrator, SubmissionResult
43
44
  from zenml.orchestrators.utils import get_orchestrator_run_name
44
- from zenml.orchestrators.wheeled_orchestrator import WheeledOrchestrator
45
- from zenml.stack import StackValidator
46
45
  from zenml.utils import code_utils, io_utils, source_utils
47
46
 
48
47
  if TYPE_CHECKING:
@@ -52,48 +51,11 @@ if TYPE_CHECKING:
52
51
 
53
52
  logger = get_logger(__name__)
54
53
  ENV_ZENML_LIGHTNING_ORCHESTRATOR_RUN_ID = "ZENML_LIGHTNING_ORCHESTRATOR_RUN_ID"
55
- ZENML_STEP_DEFAULT_ENTRYPOINT_COMMAND = "zenml.entrypoints.entrypoint"
56
54
  LIGHTNING_ZENML_DEFAULT_CUSTOM_REPOSITORY_PATH = "."
57
55
 
58
56
 
59
- class LightningOrchestrator(WheeledOrchestrator):
60
- """Base class for Orchestrator responsible for running pipelines remotely in a VM.
61
-
62
- This orchestrator does not support running on a schedule.
63
- """
64
-
65
- @property
66
- def validator(self) -> Optional[StackValidator]:
67
- """Validates the stack.
68
-
69
- In the remote case, checks that the stack contains a container registry,
70
- image builder and only remote components.
71
-
72
- Returns:
73
- A `StackValidator` instance.
74
- """
75
-
76
- def _validate_remote_components(
77
- stack: "Stack",
78
- ) -> Tuple[bool, str]:
79
- for component in stack.components.values():
80
- if not component.config.is_local:
81
- continue
82
-
83
- # return False, (
84
- # f"The Lightning orchestrator runs pipelines remotely, "
85
- # f"but the '{component.name}' {component.type.value} is "
86
- # "a local stack component and will not be available in "
87
- # "the Lightning step.\nPlease ensure that you always "
88
- # "use non-local stack components with the Lightning "
89
- # "orchestrator."
90
- # )
91
-
92
- return True, ""
93
-
94
- return StackValidator(
95
- custom_validation_function=_validate_remote_components,
96
- )
57
+ class LightningOrchestrator(BaseOrchestrator):
58
+ """Lightning orchestrator."""
97
59
 
98
60
  def _set_lightning_env_vars(
99
61
  self,
@@ -194,67 +156,39 @@ class LightningOrchestrator(WheeledOrchestrator):
194
156
  assert connector is not None
195
157
  connector.configure_local_client()
196
158
 
197
- def prepare_or_run_pipeline(
159
+ def submit_pipeline(
198
160
  self,
199
161
  deployment: "PipelineDeploymentResponse",
200
162
  stack: "Stack",
201
163
  environment: Dict[str, str],
202
164
  placeholder_run: Optional["PipelineRunResponse"] = None,
203
- ) -> Any:
204
- """Creates a wheel and uploads the pipeline to Lightning.
165
+ ) -> Optional[SubmissionResult]:
166
+ """Submits a pipeline to the orchestrator.
205
167
 
206
- This functions as an intermediary representation of the pipeline which
207
- is then deployed to the kubeflow pipelines instance.
208
-
209
- How it works:
210
- -------------
211
- Before this method is called the `prepare_pipeline_deployment()`
212
- method builds a docker image that contains the code for the
213
- pipeline, all steps the context around these files.
214
-
215
- Based on this docker image a callable is created which builds
216
- task for each step (`_construct_lightning_pipeline`).
217
- To do this the entrypoint of the docker image is configured to
218
- run the correct step within the docker image. The dependencies
219
- between these task are then also configured onto each
220
- task by pointing at the downstream steps.
168
+ This method should only submit the pipeline and not wait for it to
169
+ complete. If the orchestrator is configured to wait for the pipeline run
170
+ to complete, a function that waits for the pipeline run to complete can
171
+ be passed as part of the submission result.
221
172
 
222
173
  Args:
223
- deployment: The pipeline deployment to prepare or run.
174
+ deployment: The pipeline deployment to submit.
224
175
  stack: The stack the pipeline will run on.
225
176
  environment: Environment variables to set in the orchestration
226
- environment.
177
+ environment. These don't need to be set if running locally.
227
178
  placeholder_run: An optional placeholder run for the deployment.
228
179
 
229
- Raises:
230
- ValueError: If the schedule is not set or if the cron expression
231
- is not set.
180
+ Returns:
181
+ Optional submission result.
232
182
  """
233
183
  settings = cast(
234
184
  LightningOrchestratorSettings, self.get_settings(deployment)
235
185
  )
236
186
  if deployment.schedule:
237
- if (
238
- deployment.schedule.catchup
239
- or deployment.schedule.interval_second
240
- ):
241
- logger.warning(
242
- "Lightning orchestrator only uses schedules with the "
243
- "`cron_expression` property, with optional `start_time` and/or `end_time`. "
244
- "All other properties are ignored."
245
- )
246
- if deployment.schedule.cron_expression is None:
247
- raise ValueError(
248
- "Property `cron_expression` must be set when passing "
249
- "schedule to a Lightning orchestrator."
250
- )
251
- if deployment.schedule.cron_expression:
252
- raise ValueError(
253
- "Property `schedule_timezone` must be set when passing "
254
- "`cron_expression` to a Lightning orchestrator."
255
- "Lightning orchestrator requires a Java Timezone ID to run the pipeline on schedule."
256
- "Please refer to https://docs.oracle.com/middleware/1221/wcs/tag-ref/MISC/TimeZones.html for more information."
257
- )
187
+ logger.warning(
188
+ "Lightning Orchestrator currently does not support the "
189
+ "use of schedules. The `schedule` will be ignored "
190
+ "and the pipeline will be run immediately."
191
+ )
258
192
 
259
193
  # Get deployment id
260
194
  deployment_id = deployment.id
@@ -262,13 +196,6 @@ class LightningOrchestrator(WheeledOrchestrator):
262
196
  pipeline_name = deployment.pipeline_configuration.name
263
197
  orchestrator_run_name = get_orchestrator_run_name(pipeline_name)
264
198
 
265
- # Copy the repository to a temporary directory and add a setup.py file
266
- # repository_temp_dir = (
267
- # self.copy_repository_to_temp_dir_and_add_setup_py()
268
- # )
269
-
270
- # Create a wheel for the package in the temporary directory
271
- # wheel_path = self.create_wheel(temp_dir=repository_temp_dir)
272
199
  code_archive = code_utils.CodeArchive(
273
200
  root=source_utils.get_source_root()
274
201
  )
@@ -287,7 +214,6 @@ class LightningOrchestrator(WheeledOrchestrator):
287
214
  env_vars[ENV_ZENML_CUSTOM_SOURCE_ROOT] = (
288
215
  LIGHTNING_ZENML_DEFAULT_CUSTOM_REPOSITORY_PATH
289
216
  )
290
- env_vars[ENV_ZENML_WHEEL_PACKAGE_NAME] = self.package_name
291
217
 
292
218
  # Create a line-by-line export of environment variables
293
219
  env_exports = "\n".join(
@@ -410,7 +336,7 @@ class LightningOrchestrator(WheeledOrchestrator):
410
336
  studio.run(
411
337
  f"cd /teamspace/studios/this_studio/zenml_codes/{filename.rsplit('.', 2)[0]} && {custom_command}"
412
338
  )
413
- # studio.run(f"pip install {wheel_path.rsplit('/', 1)[-1]}")
339
+
414
340
  logger.info("Running pipeline in async mode")
415
341
  studio.run(
416
342
  f"nohup bash -c 'cd /teamspace/studios/this_studio/zenml_codes/{filename.rsplit('.', 2)[0]} && {entrypoint_string}' > log_{filename.rsplit('.', 2)[0]}.txt 2>&1 &"
@@ -430,6 +356,7 @@ class LightningOrchestrator(WheeledOrchestrator):
430
356
  env_file_path,
431
357
  )
432
358
  os.unlink(env_file_path)
359
+ return None
433
360
 
434
361
  def _upload_and_run_pipeline(
435
362
  self,
@@ -507,8 +434,7 @@ class LightningOrchestrator(WheeledOrchestrator):
507
434
 
508
435
  studio.run("pip install uv")
509
436
  studio.run(f"uv pip install {requirements}")
510
- studio.run("pip install zenml")
511
- # studio.run(f"pip install {wheel_path.rsplit('/', 1)[-1]}")
437
+ studio.run(f"uv pip install zenml=={__version__}")
512
438
  for command in settings.custom_commands or []:
513
439
  output = studio.run(
514
440
  f"cd /teamspace/studios/this_studio/zenml_codes/{filename.rsplit('.', 2)[0]} && {command}"
@@ -588,8 +514,7 @@ class LightningOrchestrator(WheeledOrchestrator):
588
514
 
589
515
  studio.run("pip install uv")
590
516
  studio.run(f"uv pip install {details['requirements']}")
591
- studio.run("pip install zenml")
592
- # studio.run(f"pip install {wheel_path.rsplit('/', 1)[-1]}")
517
+ studio.run(f"uv pip install zenml=={__version__}")
593
518
  for command in custom_commands or []:
594
519
  output = studio.run(
595
520
  f"cd /teamspace/studios/this_studio/zenml_codes/{filename.rsplit('.', 2)[0]} && {command}"
@@ -15,7 +15,7 @@
15
15
 
16
16
  import os
17
17
  from abc import abstractmethod
18
- from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, cast
18
+ from typing import TYPE_CHECKING, Dict, Optional, Tuple, cast
19
19
  from uuid import uuid4
20
20
 
21
21
  import sky
@@ -43,6 +43,7 @@ from zenml.integrations.skypilot.utils import (
43
43
  from zenml.logger import get_logger
44
44
  from zenml.orchestrators import (
45
45
  ContainerizedOrchestrator,
46
+ SubmissionResult,
46
47
  )
47
48
  from zenml.orchestrators.utils import get_orchestrator_run_name
48
49
  from zenml.stack import StackValidator
@@ -153,25 +154,33 @@ class SkypilotBaseOrchestrator(ContainerizedOrchestrator):
153
154
  set: Whether to set the environment variables or not.
154
155
  """
155
156
 
156
- def prepare_or_run_pipeline(
157
+ def submit_pipeline(
157
158
  self,
158
159
  deployment: "PipelineDeploymentResponse",
159
160
  stack: "Stack",
160
161
  environment: Dict[str, str],
161
162
  placeholder_run: Optional["PipelineRunResponse"] = None,
162
- ) -> Any:
163
- """Runs each pipeline step in a separate Skypilot container.
163
+ ) -> Optional[SubmissionResult]:
164
+ """Submits a pipeline to the orchestrator.
165
+
166
+ This method should only submit the pipeline and not wait for it to
167
+ complete. If the orchestrator is configured to wait for the pipeline run
168
+ to complete, a function that waits for the pipeline run to complete can
169
+ be passed as part of the submission result.
164
170
 
165
171
  Args:
166
- deployment: The pipeline deployment to prepare or run.
172
+ deployment: The pipeline deployment to submit.
167
173
  stack: The stack the pipeline will run on.
168
174
  environment: Environment variables to set in the orchestration
169
- environment.
175
+ environment. These don't need to be set if running locally.
170
176
  placeholder_run: An optional placeholder run for the deployment.
171
177
 
172
178
  Raises:
173
179
  Exception: If the pipeline run fails.
174
180
  RuntimeError: If the code is running in a notebook.
181
+
182
+ Returns:
183
+ Optional submission result.
175
184
  """
176
185
  # First check whether the code is running in a notebook.
177
186
  if Environment.in_notebook():
@@ -366,7 +375,9 @@ class SkypilotBaseOrchestrator(ContainerizedOrchestrator):
366
375
  cluster_name,
367
376
  **launch_kwargs,
368
377
  )
369
- sky_job_get(launch_job_id, settings.stream_logs, cluster_name)
378
+ return sky_job_get(
379
+ launch_job_id, settings.stream_logs, cluster_name
380
+ )
370
381
 
371
382
  else:
372
383
  # Prepare exec parameters with additional launch settings
@@ -399,7 +410,7 @@ class SkypilotBaseOrchestrator(ContainerizedOrchestrator):
399
410
  **exec_kwargs,
400
411
  )
401
412
  assert settings.cluster_name is not None
402
- sky_job_get(
413
+ return sky_job_get(
403
414
  exec_job_id, settings.stream_logs, settings.cluster_name
404
415
  )
405
416
 
@@ -9,6 +9,7 @@ from zenml.integrations.skypilot.flavors.skypilot_orchestrator_base_vm_config im
9
9
  SkypilotBaseOrchestratorSettings,
10
10
  )
11
11
  from zenml.logger import get_logger
12
+ from zenml.orchestrators import SubmissionResult
12
13
 
13
14
  logger = get_logger(__name__)
14
15
 
@@ -235,7 +236,9 @@ def prepare_launch_kwargs(
235
236
  return {k: v for k, v in launch_kwargs.items() if v is not None}
236
237
 
237
238
 
238
- def sky_job_get(request_id: str, stream_logs: bool, cluster_name: str) -> Any:
239
+ def sky_job_get(
240
+ request_id: str, stream_logs: bool, cluster_name: str
241
+ ) -> Optional[SubmissionResult]:
239
242
  """Handle SkyPilot request results based on stream_logs setting.
240
243
 
241
244
  SkyPilot API exec and launch methods are asynchronous and return a request ID.
@@ -249,10 +252,7 @@ def sky_job_get(request_id: str, stream_logs: bool, cluster_name: str) -> Any:
249
252
  cluster_name: The name of the cluster to tail logs for.
250
253
 
251
254
  Returns:
252
- The result of the SkyPilot operation.
253
-
254
- Raises:
255
- Exception: If the SkyPilot job fails.
255
+ Optional submission result.
256
256
  """
257
257
  if stream_logs:
258
258
  # Stream logs and wait for completion
@@ -261,13 +261,17 @@ def sky_job_get(request_id: str, stream_logs: bool, cluster_name: str) -> Any:
261
261
  # Just wait for completion without streaming logs
262
262
  job_id, _ = sky.get(request_id)
263
263
 
264
- status = 0 # 0=Successful, 100=Failed
264
+ _wait_for_completion = None
265
265
  if stream_logs:
266
- status = sky.tail_logs(
267
- cluster_name=cluster_name, job_id=job_id, follow=True
268
- )
269
-
270
- if status != 0:
271
- raise Exception(f"SkyPilot job {job_id} failed with status {status}")
272
266
 
273
- return job_id
267
+ def _wait_for_completion() -> None:
268
+ status = 0 # 0=Successful, 100=Failed
269
+ status = sky.tail_logs(
270
+ cluster_name=cluster_name, job_id=job_id, follow=True
271
+ )
272
+ if status != 0:
273
+ raise Exception(
274
+ f"SkyPilot job {job_id} failed with status {status}"
275
+ )
276
+
277
+ return SubmissionResult(wait_for_completion=_wait_for_completion)
@@ -46,7 +46,7 @@ from zenml.integrations.tekton.flavors.tekton_orchestrator_flavor import (
46
46
  )
47
47
  from zenml.io import fileio
48
48
  from zenml.logger import get_logger
49
- from zenml.orchestrators import ContainerizedOrchestrator
49
+ from zenml.orchestrators import ContainerizedOrchestrator, SubmissionResult
50
50
  from zenml.orchestrators.utils import get_orchestrator_run_name
51
51
  from zenml.stack import StackValidator
52
52
  from zenml.utils import io_utils, yaml_utils
@@ -455,28 +455,33 @@ class TektonOrchestrator(ContainerizedOrchestrator):
455
455
 
456
456
  return dsl.container_component(dynamic_func)
457
457
 
458
- def prepare_or_run_pipeline(
458
+ def submit_pipeline(
459
459
  self,
460
460
  deployment: "PipelineDeploymentResponse",
461
461
  stack: "Stack",
462
462
  environment: Dict[str, str],
463
463
  placeholder_run: Optional["PipelineRunResponse"] = None,
464
- ) -> Any:
465
- """Runs the pipeline on Tekton.
464
+ ) -> Optional[SubmissionResult]:
465
+ """Submits a pipeline to the orchestrator.
466
466
 
467
- This function first compiles the ZenML pipeline into a Tekton yaml
468
- and then applies this configuration to run the pipeline.
467
+ This method should only submit the pipeline and not wait for it to
468
+ complete. If the orchestrator is configured to wait for the pipeline run
469
+ to complete, a function that waits for the pipeline run to complete can
470
+ be passed as part of the submission result.
469
471
 
470
472
  Args:
471
- deployment: The pipeline deployment to prepare or run.
473
+ deployment: The pipeline deployment to submit.
472
474
  stack: The stack the pipeline will run on.
473
475
  environment: Environment variables to set in the orchestration
474
- environment.
476
+ environment. These don't need to be set if running locally.
475
477
  placeholder_run: An optional placeholder run for the deployment.
476
478
 
477
479
  Raises:
478
480
  RuntimeError: If you try to run the pipelines in a notebook
479
481
  environment.
482
+
483
+ Returns:
484
+ Optional submission result.
480
485
  """
481
486
  # First check whether the code running in a notebook
482
487
  if Environment.in_notebook():
@@ -640,7 +645,7 @@ class TektonOrchestrator(ContainerizedOrchestrator):
640
645
 
641
646
  # using the kfp client uploads the pipeline to Tekton pipelines and
642
647
  # runs it there
643
- self._upload_and_run_pipeline(
648
+ return self._upload_and_run_pipeline(
644
649
  deployment=deployment,
645
650
  pipeline_file_path=pipeline_file_path,
646
651
  run_name=orchestrator_run_name,
@@ -651,7 +656,7 @@ class TektonOrchestrator(ContainerizedOrchestrator):
651
656
  deployment: "PipelineDeploymentResponse",
652
657
  pipeline_file_path: str,
653
658
  run_name: str,
654
- ) -> None:
659
+ ) -> Optional[SubmissionResult]:
655
660
  """Tries to upload and run a KFP pipeline.
656
661
 
657
662
  Args:
@@ -661,6 +666,9 @@ class TektonOrchestrator(ContainerizedOrchestrator):
661
666
 
662
667
  Raises:
663
668
  RuntimeError: If Tekton API returns an error.
669
+
670
+ Returns:
671
+ Optional submission result.
664
672
  """
665
673
  pipeline_name = deployment.pipeline_configuration.name
666
674
  settings = cast(
@@ -756,8 +764,14 @@ class TektonOrchestrator(ContainerizedOrchestrator):
756
764
  )
757
765
 
758
766
  if settings.synchronous:
759
- client.wait_for_run_completion(
760
- run_id=result.run_id, timeout=settings.timeout
767
+
768
+ def _wait_for_completion() -> None:
769
+ client.wait_for_run_completion(
770
+ run_id=result.run_id, timeout=settings.timeout
771
+ )
772
+
773
+ return SubmissionResult(
774
+ wait_for_completion=_wait_for_completion
761
775
  )
762
776
  except urllib3.exceptions.HTTPError as error:
763
777
  if kubernetes_context:
@@ -779,6 +793,8 @@ class TektonOrchestrator(ContainerizedOrchestrator):
779
793
  f"Failed to upload Tekton pipeline: {error}. {msg}",
780
794
  )
781
795
 
796
+ return None
797
+
782
798
  def get_orchestrator_run_id(self) -> str:
783
799
  """Returns the active orchestrator run id.
784
800
 
@@ -129,6 +129,7 @@ class StepRunRequest(ProjectScopedRequest):
129
129
  parent_step_ids: List[UUID] = Field(
130
130
  title="The IDs of the parent steps of this step run.",
131
131
  default_factory=list,
132
+ deprecated=True,
132
133
  )
133
134
  inputs: Dict[str, List[UUID]] = Field(
134
135
  title="The IDs of the input artifact versions of the step run.",
@@ -26,6 +26,7 @@ from zenml.orchestrators.base_orchestrator import (
26
26
  BaseOrchestrator,
27
27
  BaseOrchestratorConfig,
28
28
  BaseOrchestratorFlavor,
29
+ SubmissionResult,
29
30
  )
30
31
  from zenml.orchestrators.containerized_orchestrator import (
31
32
  ContainerizedOrchestrator,
@@ -52,4 +53,5 @@ __all__ = [
52
53
  "LocalOrchestratorFlavor",
53
54
  "LocalDockerOrchestrator",
54
55
  "LocalDockerOrchestratorFlavor",
56
+ "SubmissionResult",
55
57
  ]