zenml-nightly 0.66.0.dev20240923__py3-none-any.whl → 0.66.0.dev20240928__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.
- zenml/VERSION +1 -1
- zenml/cli/__init__.py +7 -0
- zenml/cli/base.py +2 -2
- zenml/cli/pipeline.py +21 -0
- zenml/cli/utils.py +14 -11
- zenml/client.py +68 -3
- zenml/config/step_configurations.py +0 -5
- zenml/constants.py +3 -0
- zenml/enums.py +2 -0
- zenml/integrations/__init__.py +1 -0
- zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py +76 -7
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +370 -115
- zenml/integrations/azure/__init__.py +6 -2
- zenml/integrations/azure/orchestrators/azureml_orchestrator.py +157 -4
- zenml/integrations/constants.py +1 -0
- zenml/integrations/deepchecks/__init__.py +1 -1
- zenml/integrations/deepchecks/data_validators/deepchecks_data_validator.py +55 -14
- zenml/integrations/deepchecks/validation_checks.py +62 -5
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +207 -18
- zenml/integrations/lightning/__init__.py +1 -1
- zenml/integrations/lightning/flavors/lightning_orchestrator_flavor.py +9 -0
- zenml/integrations/lightning/orchestrators/lightning_orchestrator.py +18 -17
- zenml/integrations/lightning/orchestrators/lightning_orchestrator_entrypoint.py +2 -6
- zenml/integrations/mlflow/steps/mlflow_registry.py +2 -0
- zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +38 -26
- zenml/integrations/skypilot_kubernetes/__init__.py +52 -0
- zenml/integrations/skypilot_kubernetes/flavors/__init__.py +26 -0
- zenml/integrations/skypilot_kubernetes/flavors/skypilot_orchestrator_kubernetes_vm_flavor.py +125 -0
- zenml/integrations/skypilot_kubernetes/orchestrators/__init__.py +25 -0
- zenml/integrations/skypilot_kubernetes/orchestrators/skypilot_kubernetes_vm_orchestrator.py +74 -0
- zenml/integrations/tensorboard/visualizers/tensorboard_visualizer.py +1 -1
- zenml/models/v2/base/filter.py +315 -149
- zenml/models/v2/base/scoped.py +5 -2
- zenml/models/v2/core/artifact_version.py +69 -8
- zenml/models/v2/core/model.py +43 -6
- zenml/models/v2/core/model_version.py +49 -1
- zenml/models/v2/core/model_version_artifact.py +18 -3
- zenml/models/v2/core/model_version_pipeline_run.py +18 -4
- zenml/models/v2/core/pipeline.py +108 -1
- zenml/models/v2/core/pipeline_run.py +172 -21
- zenml/models/v2/core/run_template.py +53 -1
- zenml/models/v2/core/stack.py +33 -5
- zenml/models/v2/core/step_run.py +7 -0
- zenml/new/pipelines/pipeline.py +4 -0
- zenml/new/pipelines/run_utils.py +4 -1
- zenml/orchestrators/base_orchestrator.py +41 -12
- zenml/stack/stack.py +11 -2
- zenml/utils/env_utils.py +54 -1
- zenml/utils/string_utils.py +50 -0
- zenml/zen_server/cloud_utils.py +33 -8
- zenml/zen_server/dashboard/assets/{404-iO8vpun1.js → 404-Y50hSt65.js} +1 -1
- zenml/zen_server/dashboard/assets/{@reactflow-B6kq9fJZ.js → @reactflow-ytavUpwh.js} +1 -1
- zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-xLR9a1iw.js +1 -0
- zenml/zen_server/dashboard/assets/{CodeSnippet-DNWdQmbo.js → CodeSnippet-IxXNxUDa.js} +2 -2
- zenml/zen_server/dashboard/assets/{CollapsibleCard-B2OVjWYE.js → CollapsibleCard-BhutZbBL.js} +1 -1
- zenml/zen_server/dashboard/assets/{Commands-DsoaVElZ.js → Commands-Bf-rd1z8.js} +1 -1
- zenml/zen_server/dashboard/assets/ComponentBadge-gKR1OIwG.js +1 -0
- zenml/zen_server/dashboard/assets/{CopyButton-BqE_-PHO.js → CopyButton-DcFHidFJ.js} +1 -1
- zenml/zen_server/dashboard/assets/{CsvVizualization-Dyasr2jU.js → CsvVizualization-QSbjrfxw.js} +1 -1
- zenml/zen_server/dashboard/assets/{DialogItem-Cz1VLRwa.js → DialogItem-Cd3HqST4.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-DorJD_va.js → Error-BhwdmqK7.js} +1 -1
- zenml/zen_server/dashboard/assets/{ExecutionStatus-CIfQTutR.js → ExecutionStatus-D6r6aK8J.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-CmfvtNeq.js → Helpbox-0pBpTwTm.js} +1 -1
- zenml/zen_server/dashboard/assets/Infobox-BTK_EUKT.js +1 -0
- zenml/zen_server/dashboard/assets/{InlineAvatar-Ds2ZFHPc.js → InlineAvatar-CA3DFMcM.js} +1 -1
- zenml/zen_server/dashboard/assets/Partials-QLOZw624.js +1 -0
- zenml/zen_server/dashboard/assets/{ProviderIcon-BOQJgapd.js → ProviderIcon-C16CCIN4.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderRadio-BsYBw9YA.js → ProviderRadio-D3FuCHf3.js} +1 -1
- zenml/zen_server/dashboard/assets/{SearchField-W3GXpLlI.js → SearchField-BzmfxS0L.js} +1 -1
- zenml/zen_server/dashboard/assets/SecretTooltip-BaMwHF-Q.js +1 -0
- zenml/zen_server/dashboard/assets/{SetPassword-B-0a8UCj.js → SetPassword-DuIC65H9.js} +1 -1
- zenml/zen_server/dashboard/assets/{Tick-i1DYsVcX.js → Tick-DJTCF0Re.js} +1 -1
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-C6Zb7ASL.js → UpdatePasswordSchemas-CUm-DMpw.js} +1 -1
- zenml/zen_server/dashboard/assets/UsageReason-CKw0juLF.js +1 -0
- zenml/zen_server/dashboard/assets/{WizardFooter-BHbO7zOa.js → WizardFooter-Cv9ApYWU.js} +1 -1
- zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-BBEe6I9-.js → all-pipeline-runs-query-BA3R2Sey.js} +1 -1
- zenml/zen_server/dashboard/assets/{cloud-only-BuP4Kt_7.js → cloud-only-BB4BVa6E.js} +1 -1
- zenml/zen_server/dashboard/assets/{create-stack-B2x2d4r1.js → create-stack-F29xAUEx.js} +1 -1
- zenml/zen_server/dashboard/assets/delete-run-CP0pcJ3U.js +1 -0
- zenml/zen_server/dashboard/assets/{form-schemas-Bap0f854.js → form-schemas-BKXwSDK2.js} +1 -1
- zenml/zen_server/dashboard/assets/index-BhJ6ZJxv.css +1 -0
- zenml/zen_server/dashboard/assets/{index-B9wVwe7u.js → index-Ci0nJ8EZ.js} +5 -5
- zenml/zen_server/dashboard/assets/{index-DFi8BroH.js → index-D-mtoBj3.js} +1 -1
- zenml/zen_server/dashboard/assets/{login-mutation-DwxUz8VA.js → login-mutation-ax6iL2Mb.js} +1 -1
- zenml/zen_server/dashboard/assets/{not-found-D5i9DunU.js → not-found-DbjllLY_.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-oS4hqS8M.js → page-3qPX9WYH.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-iwoJnwPv.js → page-6mfzecin.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DGMa3ZQL.js → page-8kYmrh0B.js} +1 -1
- zenml/zen_server/dashboard/assets/page-B1n7_W7z.js +1 -0
- zenml/zen_server/dashboard/assets/page-BDg1F-Ug.js +6 -0
- zenml/zen_server/dashboard/assets/{page-xQG6GmFJ.js → page-BXarY9K2.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BZZhLo2u.js +1 -0
- zenml/zen_server/dashboard/assets/page-Bbf_oBjn.js +1 -0
- zenml/zen_server/dashboard/assets/page-BjjuBvZG.js +9 -0
- zenml/zen_server/dashboard/assets/{page-J0s8Sq3N.js → page-BukXK1Aa.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CHaQkFK5.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BitfWsiW.js → page-CKHNAq7z.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DE03uZZR.js → page-CS0SYFK8.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-WCQ659by.js → page-CvKnNK1S.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CrSdkteO.js → page-DGM1CbYT.js} +2 -2
- zenml/zen_server/dashboard/assets/{page-DQGCHKrQ.js → page-DMSLXKGT.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DOmIZ2ra.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DgM-N9RL.js → page-DRfcRK1w.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DYVmJ9_w.js +3 -0
- zenml/zen_server/dashboard/assets/{page-BiF8hLbO.js → page-DcTjHmYZ.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DuqYMYmH.js +1 -0
- zenml/zen_server/dashboard/assets/page-Dwow2doB.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DQdwZZ9x.js → page-HkVBdZl6.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-bimkItOg.js → page-MAXyfXBq.js} +1 -1
- zenml/zen_server/dashboard/assets/page-miU2rhYG.js +1 -0
- zenml/zen_server/dashboard/assets/page-p0BhSAWx.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DFCK65G9.js → page-uORspyRu.js} +1 -1
- zenml/zen_server/dashboard/assets/persist-BxIR2XZs.js +1 -0
- zenml/zen_server/dashboard/assets/{persist-xsYgVtR1.js → persist-CfJMar_k.js} +1 -1
- zenml/zen_server/dashboard/assets/sharedSchema-vub0rii3.js +14 -0
- zenml/zen_server/dashboard/assets/stack-detail-query-DQcyzG-2.js +1 -0
- zenml/zen_server/dashboard/assets/tick-circle-m-hJG8i9.js +1 -0
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-DNqmQXDM.js → update-server-settings-mutation-FGVP7X2U.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-DwbuKk1b.js → url-CbAPzsmT.js} +1 -1
- zenml/zen_server/dashboard/index.html +4 -4
- zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
- zenml/zen_server/dashboard_legacy/index.html +1 -1
- zenml/zen_server/dashboard_legacy/{precache-manifest.290b95d5b43efa3368b3dc63d20c4782.js → precache-manifest.6d320abb70db612019dda6c4948e7a90.js} +4 -4
- zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
- zenml/zen_server/dashboard_legacy/static/js/{main.840d1bf0.chunk.js → main.fa9299d5.chunk.js} +2 -2
- zenml/zen_server/dashboard_legacy/static/js/{main.840d1bf0.chunk.js.map → main.fa9299d5.chunk.js.map} +1 -1
- zenml/zen_server/routers/runs_endpoints.py +89 -3
- zenml/zen_stores/sql_zen_store.py +1 -0
- {zenml_nightly-0.66.0.dev20240923.dist-info → zenml_nightly-0.66.0.dev20240928.dist-info}/METADATA +8 -1
- {zenml_nightly-0.66.0.dev20240923.dist-info → zenml_nightly-0.66.0.dev20240928.dist-info}/RECORD +133 -125
- zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-BXeSvmMY.js +0 -1
- zenml/zen_server/dashboard/assets/EditSecretDialog-Du423_3U.js +0 -1
- zenml/zen_server/dashboard/assets/Infobox-BL9NOS37.js +0 -1
- zenml/zen_server/dashboard/assets/Partials-DX-8iEa1.js +0 -1
- zenml/zen_server/dashboard/assets/UsageReason-CCnzmwS8.js +0 -1
- zenml/zen_server/dashboard/assets/index-6DYjZgDn.css +0 -1
- zenml/zen_server/dashboard/assets/page-BFuJICXM.js +0 -9
- zenml/zen_server/dashboard/assets/page-CDOQLrPC.js +0 -1
- zenml/zen_server/dashboard/assets/page-CEJWu1YO.js +0 -1
- zenml/zen_server/dashboard/assets/page-CIbehp7V.js +0 -1
- zenml/zen_server/dashboard/assets/page-CLiRGfWo.js +0 -1
- zenml/zen_server/dashboard/assets/page-CV44mQn9.js +0 -1
- zenml/zen_server/dashboard/assets/page-D5F3DJjm.js +0 -1
- zenml/zen_server/dashboard/assets/page-DI-qTWrm.js +0 -1
- zenml/zen_server/dashboard/assets/page-Dt8VgzbE.js +0 -1
- zenml/zen_server/dashboard/assets/page-oSqx9dkH.js +0 -1
- zenml/zen_server/dashboard/assets/page-p3GqEAUW.js +0 -1
- zenml/zen_server/dashboard/assets/page-qvcUVPE-.js +0 -1
- zenml/zen_server/dashboard/assets/persist-mEZN_fgH.js +0 -1
- zenml/zen_server/dashboard/assets/sharedSchema-BfZcy7aP.js +0 -14
- zenml/zen_server/dashboard/assets/stack-detail-query-CU4egfhp.js +0 -1
- {zenml_nightly-0.66.0.dev20240923.dist-info → zenml_nightly-0.66.0.dev20240928.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.66.0.dev20240923.dist-info → zenml_nightly-0.66.0.dev20240928.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.66.0.dev20240923.dist-info → zenml_nightly-0.66.0.dev20240928.dist-info}/entry_points.txt +0 -0
@@ -21,6 +21,7 @@ from typing import (
|
|
21
21
|
List,
|
22
22
|
Optional,
|
23
23
|
Union,
|
24
|
+
cast,
|
24
25
|
)
|
25
26
|
from uuid import UUID
|
26
27
|
|
@@ -28,8 +29,7 @@ from pydantic import BaseModel, ConfigDict, Field
|
|
28
29
|
|
29
30
|
from zenml.config.pipeline_configurations import PipelineConfiguration
|
30
31
|
from zenml.constants import STR_FIELD_MAX_LENGTH
|
31
|
-
from zenml.enums import ExecutionStatus
|
32
|
-
from zenml.models.v2.base.filter import StrFilter
|
32
|
+
from zenml.enums import ExecutionStatus
|
33
33
|
from zenml.models.v2.base.scoped import (
|
34
34
|
WorkspaceScopedFilter,
|
35
35
|
WorkspaceScopedRequest,
|
@@ -137,7 +137,8 @@ class PipelineRunUpdate(BaseModel):
|
|
137
137
|
"configured by this pipeline run explicitly.",
|
138
138
|
default=None,
|
139
139
|
)
|
140
|
-
# TODO: we should maybe have a different update model here, the upper
|
140
|
+
# TODO: we should maybe have a different update model here, the upper
|
141
|
+
# three attributes should only be for internal use
|
141
142
|
add_tags: Optional[List[str]] = Field(
|
142
143
|
default=None, title="New tags to add to the pipeline run."
|
143
144
|
)
|
@@ -236,6 +237,7 @@ class PipelineRunResponseMetadata(WorkspaceScopedResponseMetadata):
|
|
236
237
|
description="Template used for the pipeline run.",
|
237
238
|
)
|
238
239
|
is_templatable: bool = Field(
|
240
|
+
default=False,
|
239
241
|
description="Whether a template can be created from this run.",
|
240
242
|
)
|
241
243
|
|
@@ -308,6 +310,64 @@ class PipelineRunResponse(
|
|
308
310
|
|
309
311
|
return get_artifacts_versions_of_pipeline_run(self, only_produced=True)
|
310
312
|
|
313
|
+
def refresh_run_status(self) -> "PipelineRunResponse":
|
314
|
+
"""Method to refresh the status of a run if it is initializing/running.
|
315
|
+
|
316
|
+
Returns:
|
317
|
+
The updated pipeline.
|
318
|
+
|
319
|
+
Raises:
|
320
|
+
ValueError: If the stack of the run response is None.
|
321
|
+
"""
|
322
|
+
if self.status in [
|
323
|
+
ExecutionStatus.INITIALIZING,
|
324
|
+
ExecutionStatus.RUNNING,
|
325
|
+
]:
|
326
|
+
# Check if the stack still accessible
|
327
|
+
if self.stack is None:
|
328
|
+
raise ValueError(
|
329
|
+
"The stack that this pipeline run response was executed on"
|
330
|
+
"has been deleted."
|
331
|
+
)
|
332
|
+
|
333
|
+
# Create the orchestrator instance
|
334
|
+
from zenml.enums import StackComponentType
|
335
|
+
from zenml.orchestrators.base_orchestrator import BaseOrchestrator
|
336
|
+
from zenml.stack.stack_component import StackComponent
|
337
|
+
|
338
|
+
# Check if the stack still accessible
|
339
|
+
orchestrator_list = self.stack.components.get(
|
340
|
+
StackComponentType.ORCHESTRATOR, []
|
341
|
+
)
|
342
|
+
if len(orchestrator_list) == 0:
|
343
|
+
raise ValueError(
|
344
|
+
"The orchestrator that this pipeline run response was "
|
345
|
+
"executed with has been deleted."
|
346
|
+
)
|
347
|
+
|
348
|
+
orchestrator = cast(
|
349
|
+
BaseOrchestrator,
|
350
|
+
StackComponent.from_model(
|
351
|
+
component_model=orchestrator_list[0]
|
352
|
+
),
|
353
|
+
)
|
354
|
+
|
355
|
+
# Fetch the status
|
356
|
+
status = orchestrator.fetch_status(run=self)
|
357
|
+
|
358
|
+
# If it is different from the current status, update it
|
359
|
+
if status != self.status:
|
360
|
+
from zenml.client import Client
|
361
|
+
from zenml.models import PipelineRunUpdate
|
362
|
+
|
363
|
+
client = Client()
|
364
|
+
return client.zen_store.update_run(
|
365
|
+
run_id=self.id,
|
366
|
+
run_update=PipelineRunUpdate(status=status),
|
367
|
+
)
|
368
|
+
|
369
|
+
return self
|
370
|
+
|
311
371
|
# Body and metadata properties
|
312
372
|
@property
|
313
373
|
def status(self) -> ExecutionStatus:
|
@@ -522,6 +582,11 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
522
582
|
"schedule_id",
|
523
583
|
"stack_id",
|
524
584
|
"template_id",
|
585
|
+
"user",
|
586
|
+
"pipeline",
|
587
|
+
"stack",
|
588
|
+
"code_repository",
|
589
|
+
"model",
|
525
590
|
"pipeline_name",
|
526
591
|
"templatable",
|
527
592
|
]
|
@@ -538,10 +603,6 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
538
603
|
description="Pipeline associated with the Pipeline Run",
|
539
604
|
union_mode="left_to_right",
|
540
605
|
)
|
541
|
-
pipeline_name: Optional[str] = Field(
|
542
|
-
default=None,
|
543
|
-
description="Name of the pipeline associated with the run",
|
544
|
-
)
|
545
606
|
workspace_id: Optional[Union[UUID, str]] = Field(
|
546
607
|
default=None,
|
547
608
|
description="Workspace of the Pipeline Run",
|
@@ -582,6 +643,11 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
582
643
|
description="Template used for the pipeline run.",
|
583
644
|
union_mode="left_to_right",
|
584
645
|
)
|
646
|
+
model_version_id: Optional[Union[UUID, str]] = Field(
|
647
|
+
default=None,
|
648
|
+
description="Model version associated with the pipeline run.",
|
649
|
+
union_mode="left_to_right",
|
650
|
+
)
|
585
651
|
status: Optional[str] = Field(
|
586
652
|
default=None,
|
587
653
|
description="Name of the Pipeline Run",
|
@@ -597,7 +663,37 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
597
663
|
union_mode="left_to_right",
|
598
664
|
)
|
599
665
|
unlisted: Optional[bool] = None
|
600
|
-
|
666
|
+
user: Optional[Union[UUID, str]] = Field(
|
667
|
+
default=None,
|
668
|
+
description="Name/ID of the user that created the run.",
|
669
|
+
)
|
670
|
+
# TODO: Remove once frontend is ready for it. This is replaced by the more
|
671
|
+
# generic `pipeline` filter below.
|
672
|
+
pipeline_name: Optional[str] = Field(
|
673
|
+
default=None,
|
674
|
+
description="Name of the pipeline associated with the run",
|
675
|
+
)
|
676
|
+
pipeline: Optional[Union[UUID, str]] = Field(
|
677
|
+
default=None,
|
678
|
+
description="Name/ID of the pipeline associated with the run.",
|
679
|
+
)
|
680
|
+
stack: Optional[Union[UUID, str]] = Field(
|
681
|
+
default=None,
|
682
|
+
description="Name/ID of the stack associated with the run.",
|
683
|
+
)
|
684
|
+
code_repository: Optional[Union[UUID, str]] = Field(
|
685
|
+
default=None,
|
686
|
+
description="Name/ID of the code repository associated with the run.",
|
687
|
+
)
|
688
|
+
model: Optional[Union[UUID, str]] = Field(
|
689
|
+
default=None,
|
690
|
+
description="Name/ID of the model associated with the run.",
|
691
|
+
)
|
692
|
+
templatable: Optional[bool] = Field(
|
693
|
+
default=None, description="Whether the run is templatable."
|
694
|
+
)
|
695
|
+
|
696
|
+
model_config = ConfigDict(protected_namespaces=())
|
601
697
|
|
602
698
|
def get_custom_filters(
|
603
699
|
self,
|
@@ -613,12 +709,16 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
613
709
|
|
614
710
|
from zenml.zen_stores.schemas import (
|
615
711
|
CodeReferenceSchema,
|
712
|
+
CodeRepositorySchema,
|
713
|
+
ModelSchema,
|
714
|
+
ModelVersionSchema,
|
616
715
|
PipelineBuildSchema,
|
617
716
|
PipelineDeploymentSchema,
|
618
717
|
PipelineRunSchema,
|
619
718
|
PipelineSchema,
|
620
719
|
ScheduleSchema,
|
621
720
|
StackSchema,
|
721
|
+
UserSchema,
|
622
722
|
)
|
623
723
|
|
624
724
|
if self.unlisted is not None:
|
@@ -628,19 +728,6 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
628
728
|
unlisted_filter = PipelineRunSchema.pipeline_id.is_not(None) # type: ignore[union-attr]
|
629
729
|
custom_filters.append(unlisted_filter)
|
630
730
|
|
631
|
-
if self.pipeline_name is not None:
|
632
|
-
value, filter_operator = self._resolve_operator(self.pipeline_name)
|
633
|
-
filter_ = StrFilter(
|
634
|
-
operation=GenericFilterOps(filter_operator),
|
635
|
-
column="name",
|
636
|
-
value=value,
|
637
|
-
)
|
638
|
-
pipeline_name_filter = and_(
|
639
|
-
PipelineRunSchema.pipeline_id == PipelineSchema.id,
|
640
|
-
filter_.generate_query_conditions(PipelineSchema),
|
641
|
-
)
|
642
|
-
custom_filters.append(pipeline_name_filter)
|
643
|
-
|
644
731
|
if self.code_repository_id:
|
645
732
|
code_repo_filter = and_(
|
646
733
|
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
|
@@ -682,6 +769,70 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
682
769
|
)
|
683
770
|
custom_filters.append(run_template_filter)
|
684
771
|
|
772
|
+
if self.user:
|
773
|
+
user_filter = and_(
|
774
|
+
PipelineRunSchema.user_id == UserSchema.id,
|
775
|
+
self.generate_name_or_id_query_conditions(
|
776
|
+
value=self.user, table=UserSchema
|
777
|
+
),
|
778
|
+
)
|
779
|
+
custom_filters.append(user_filter)
|
780
|
+
|
781
|
+
if self.pipeline:
|
782
|
+
pipeline_filter = and_(
|
783
|
+
PipelineRunSchema.pipeline_id == PipelineSchema.id,
|
784
|
+
self.generate_name_or_id_query_conditions(
|
785
|
+
value=self.pipeline, table=PipelineSchema
|
786
|
+
),
|
787
|
+
)
|
788
|
+
custom_filters.append(pipeline_filter)
|
789
|
+
|
790
|
+
if self.stack:
|
791
|
+
stack_filter = and_(
|
792
|
+
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
|
793
|
+
PipelineDeploymentSchema.stack_id == StackSchema.id,
|
794
|
+
self.generate_name_or_id_query_conditions(
|
795
|
+
value=self.stack,
|
796
|
+
table=StackSchema,
|
797
|
+
),
|
798
|
+
)
|
799
|
+
custom_filters.append(stack_filter)
|
800
|
+
|
801
|
+
if self.code_repository:
|
802
|
+
code_repo_filter = and_(
|
803
|
+
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
|
804
|
+
PipelineDeploymentSchema.code_reference_id
|
805
|
+
== CodeReferenceSchema.id,
|
806
|
+
CodeReferenceSchema.code_repository_id
|
807
|
+
== CodeRepositorySchema.id,
|
808
|
+
self.generate_name_or_id_query_conditions(
|
809
|
+
value=self.code_repository,
|
810
|
+
table=CodeRepositorySchema,
|
811
|
+
),
|
812
|
+
)
|
813
|
+
custom_filters.append(code_repo_filter)
|
814
|
+
|
815
|
+
if self.model:
|
816
|
+
model_filter = and_(
|
817
|
+
PipelineRunSchema.model_version_id == ModelVersionSchema.id,
|
818
|
+
ModelVersionSchema.model_id == ModelSchema.id,
|
819
|
+
self.generate_name_or_id_query_conditions(
|
820
|
+
value=self.model, table=ModelSchema
|
821
|
+
),
|
822
|
+
)
|
823
|
+
custom_filters.append(model_filter)
|
824
|
+
|
825
|
+
if self.pipeline_name:
|
826
|
+
pipeline_name_filter = and_(
|
827
|
+
PipelineRunSchema.pipeline_id == PipelineSchema.id,
|
828
|
+
self.generate_custom_query_conditions_for_column(
|
829
|
+
value=self.pipeline_name,
|
830
|
+
table=PipelineSchema,
|
831
|
+
column="name",
|
832
|
+
),
|
833
|
+
)
|
834
|
+
custom_filters.append(pipeline_name_filter)
|
835
|
+
|
685
836
|
if self.templatable is not None:
|
686
837
|
if self.templatable is True:
|
687
838
|
templatable_filter = and_(
|
@@ -299,7 +299,11 @@ class RunTemplateFilter(WorkspaceScopedTaggableFilter):
|
|
299
299
|
*WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
|
300
300
|
"code_repository_id",
|
301
301
|
"stack_id",
|
302
|
-
"build_id"
|
302
|
+
"build_id",
|
303
|
+
"pipeline_id",
|
304
|
+
"user",
|
305
|
+
"pipeline",
|
306
|
+
"stack",
|
303
307
|
]
|
304
308
|
|
305
309
|
name: Optional[str] = Field(
|
@@ -336,6 +340,18 @@ class RunTemplateFilter(WorkspaceScopedTaggableFilter):
|
|
336
340
|
description="Code repository associated with the template.",
|
337
341
|
union_mode="left_to_right",
|
338
342
|
)
|
343
|
+
user: Optional[Union[UUID, str]] = Field(
|
344
|
+
default=None,
|
345
|
+
description="Name/ID of the user that created the template.",
|
346
|
+
)
|
347
|
+
pipeline: Optional[Union[UUID, str]] = Field(
|
348
|
+
default=None,
|
349
|
+
description="Name/ID of the pipeline associated with the template.",
|
350
|
+
)
|
351
|
+
stack: Optional[Union[UUID, str]] = Field(
|
352
|
+
default=None,
|
353
|
+
description="Name/ID of the stack associated with the template.",
|
354
|
+
)
|
339
355
|
|
340
356
|
def get_custom_filters(
|
341
357
|
self,
|
@@ -352,7 +368,10 @@ class RunTemplateFilter(WorkspaceScopedTaggableFilter):
|
|
352
368
|
from zenml.zen_stores.schemas import (
|
353
369
|
CodeReferenceSchema,
|
354
370
|
PipelineDeploymentSchema,
|
371
|
+
PipelineSchema,
|
355
372
|
RunTemplateSchema,
|
373
|
+
StackSchema,
|
374
|
+
UserSchema,
|
356
375
|
)
|
357
376
|
|
358
377
|
if self.code_repository_id:
|
@@ -390,4 +409,37 @@ class RunTemplateFilter(WorkspaceScopedTaggableFilter):
|
|
390
409
|
)
|
391
410
|
custom_filters.append(pipeline_filter)
|
392
411
|
|
412
|
+
if self.user:
|
413
|
+
user_filter = and_(
|
414
|
+
RunTemplateSchema.user_id == UserSchema.id,
|
415
|
+
self.generate_name_or_id_query_conditions(
|
416
|
+
value=self.user, table=UserSchema
|
417
|
+
),
|
418
|
+
)
|
419
|
+
custom_filters.append(user_filter)
|
420
|
+
|
421
|
+
if self.pipeline:
|
422
|
+
pipeline_filter = and_(
|
423
|
+
RunTemplateSchema.source_deployment_id
|
424
|
+
== PipelineDeploymentSchema.id,
|
425
|
+
PipelineDeploymentSchema.pipeline_id == PipelineSchema.id,
|
426
|
+
self.generate_name_or_id_query_conditions(
|
427
|
+
value=self.pipeline,
|
428
|
+
table=PipelineSchema,
|
429
|
+
),
|
430
|
+
)
|
431
|
+
custom_filters.append(pipeline_filter)
|
432
|
+
|
433
|
+
if self.stack:
|
434
|
+
stack_filter = and_(
|
435
|
+
RunTemplateSchema.source_deployment_id
|
436
|
+
== PipelineDeploymentSchema.id,
|
437
|
+
PipelineDeploymentSchema.stack_id == StackSchema.id,
|
438
|
+
self.generate_name_or_id_query_conditions(
|
439
|
+
value=self.stack,
|
440
|
+
table=StackSchema,
|
441
|
+
),
|
442
|
+
)
|
443
|
+
custom_filters.append(stack_filter)
|
444
|
+
|
393
445
|
return custom_filters
|
zenml/models/v2/core/stack.py
CHANGED
@@ -318,12 +318,11 @@ class StackFilter(WorkspaceScopedFilter):
|
|
318
318
|
scoping.
|
319
319
|
"""
|
320
320
|
|
321
|
-
# `component_id` refers to a relationship through a link-table
|
322
|
-
# rather than a field in the db, hence it needs to be handled
|
323
|
-
# explicitly
|
324
321
|
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
|
325
322
|
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
|
326
|
-
"component_id",
|
323
|
+
"component_id",
|
324
|
+
"user",
|
325
|
+
"component",
|
327
326
|
]
|
328
327
|
|
329
328
|
name: Optional[str] = Field(
|
@@ -348,6 +347,13 @@ class StackFilter(WorkspaceScopedFilter):
|
|
348
347
|
description="Component in the stack",
|
349
348
|
union_mode="left_to_right",
|
350
349
|
)
|
350
|
+
user: Optional[Union[UUID, str]] = Field(
|
351
|
+
default=None,
|
352
|
+
description="Name/ID of the user that created the stack.",
|
353
|
+
)
|
354
|
+
component: Optional[Union[UUID, str]] = Field(
|
355
|
+
default=None, description="Name/ID of a component in the stack."
|
356
|
+
)
|
351
357
|
|
352
358
|
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
|
353
359
|
"""Get custom filters.
|
@@ -357,9 +363,11 @@ class StackFilter(WorkspaceScopedFilter):
|
|
357
363
|
"""
|
358
364
|
custom_filters = super().get_custom_filters()
|
359
365
|
|
360
|
-
from zenml.zen_stores.schemas
|
366
|
+
from zenml.zen_stores.schemas import (
|
367
|
+
StackComponentSchema,
|
361
368
|
StackCompositionSchema,
|
362
369
|
StackSchema,
|
370
|
+
UserSchema,
|
363
371
|
)
|
364
372
|
|
365
373
|
if self.component_id:
|
@@ -369,4 +377,24 @@ class StackFilter(WorkspaceScopedFilter):
|
|
369
377
|
)
|
370
378
|
custom_filters.append(component_id_filter)
|
371
379
|
|
380
|
+
if self.user:
|
381
|
+
user_filter = and_(
|
382
|
+
StackSchema.user_id == UserSchema.id,
|
383
|
+
self.generate_name_or_id_query_conditions(
|
384
|
+
value=self.user, table=UserSchema
|
385
|
+
),
|
386
|
+
)
|
387
|
+
custom_filters.append(user_filter)
|
388
|
+
|
389
|
+
if self.component:
|
390
|
+
component_filter = and_(
|
391
|
+
StackCompositionSchema.stack_id == StackSchema.id,
|
392
|
+
StackCompositionSchema.component_id == StackComponentSchema.id,
|
393
|
+
self.generate_name_or_id_query_conditions(
|
394
|
+
value=self.component,
|
395
|
+
table=StackComponentSchema,
|
396
|
+
),
|
397
|
+
)
|
398
|
+
custom_filters.append(component_filter)
|
399
|
+
|
372
400
|
return custom_filters
|
zenml/models/v2/core/step_run.py
CHANGED
@@ -536,3 +536,10 @@ class StepRunFilter(WorkspaceScopedFilter):
|
|
536
536
|
description="Workspace of this step run",
|
537
537
|
union_mode="left_to_right",
|
538
538
|
)
|
539
|
+
model_version_id: Optional[Union[UUID, str]] = Field(
|
540
|
+
default=None,
|
541
|
+
description="Model version associated with the pipeline run.",
|
542
|
+
union_mode="left_to_right",
|
543
|
+
)
|
544
|
+
|
545
|
+
model_config = ConfigDict(protected_namespaces=())
|
zenml/new/pipelines/pipeline.py
CHANGED
@@ -84,6 +84,7 @@ from zenml.utils import (
|
|
84
84
|
code_utils,
|
85
85
|
dashboard_utils,
|
86
86
|
dict_utils,
|
87
|
+
env_utils,
|
87
88
|
pydantic_utils,
|
88
89
|
settings_utils,
|
89
90
|
source_utils,
|
@@ -1030,12 +1031,14 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
1030
1031
|
|
1031
1032
|
# Update with the values in code so they take precedence
|
1032
1033
|
run_config = pydantic_utils.update_model(run_config, update=update)
|
1034
|
+
run_config = env_utils.substitute_env_variable_placeholders(run_config)
|
1033
1035
|
|
1034
1036
|
deployment = Compiler().compile(
|
1035
1037
|
pipeline=self,
|
1036
1038
|
stack=Client().active_stack,
|
1037
1039
|
run_configuration=run_config,
|
1038
1040
|
)
|
1041
|
+
deployment = env_utils.substitute_env_variable_placeholders(deployment)
|
1039
1042
|
|
1040
1043
|
return deployment, run_config.schedule, run_config.build
|
1041
1044
|
|
@@ -1252,6 +1255,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
1252
1255
|
if config_path:
|
1253
1256
|
with open(config_path, "r") as f:
|
1254
1257
|
_from_config_file = yaml.load(f, Loader=yaml.SafeLoader)
|
1258
|
+
|
1255
1259
|
_from_config_file = dict_utils.remove_none_values(
|
1256
1260
|
{k: v for k, v in _from_config_file.items() if k in matcher}
|
1257
1261
|
)
|
zenml/new/pipelines/run_utils.py
CHANGED
@@ -138,7 +138,10 @@ def deploy_pipeline(
|
|
138
138
|
previous_value = constants.SHOULD_PREVENT_PIPELINE_EXECUTION
|
139
139
|
constants.SHOULD_PREVENT_PIPELINE_EXECUTION = True
|
140
140
|
try:
|
141
|
-
stack.deploy_pipeline(
|
141
|
+
stack.deploy_pipeline(
|
142
|
+
deployment=deployment,
|
143
|
+
placeholder_run=placeholder_run,
|
144
|
+
)
|
142
145
|
except Exception as e:
|
143
146
|
if (
|
144
147
|
placeholder_run
|
@@ -14,12 +14,14 @@
|
|
14
14
|
"""Base orchestrator class."""
|
15
15
|
|
16
16
|
from abc import ABC, abstractmethod
|
17
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional, Type, cast
|
17
|
+
from typing import TYPE_CHECKING, Any, Dict, Iterator, Optional, Type, cast
|
18
18
|
|
19
19
|
from pydantic import model_validator
|
20
20
|
|
21
|
-
from zenml.enums import StackComponentType
|
21
|
+
from zenml.enums import ExecutionStatus, StackComponentType
|
22
22
|
from zenml.logger import get_logger
|
23
|
+
from zenml.metadata.metadata_types import MetadataType
|
24
|
+
from zenml.orchestrators.publish_utils import publish_pipeline_run_metadata
|
23
25
|
from zenml.orchestrators.step_launcher import StepLauncher
|
24
26
|
from zenml.orchestrators.utils import get_config_environment_vars
|
25
27
|
from zenml.stack import Flavor, Stack, StackComponent, StackComponentConfig
|
@@ -27,7 +29,7 @@ from zenml.utils.pydantic_utils import before_validator_handler
|
|
27
29
|
|
28
30
|
if TYPE_CHECKING:
|
29
31
|
from zenml.config.step_configurations import Step
|
30
|
-
from zenml.models import PipelineDeploymentResponse
|
32
|
+
from zenml.models import PipelineDeploymentResponse, PipelineRunResponse
|
31
33
|
|
32
34
|
logger = get_logger(__name__)
|
33
35
|
|
@@ -124,7 +126,7 @@ class BaseOrchestrator(StackComponent, ABC):
|
|
124
126
|
deployment: "PipelineDeploymentResponse",
|
125
127
|
stack: "Stack",
|
126
128
|
environment: Dict[str, str],
|
127
|
-
) ->
|
129
|
+
) -> Optional[Iterator[Dict[str, MetadataType]]]:
|
128
130
|
"""The method needs to be implemented by the respective orchestrator.
|
129
131
|
|
130
132
|
Depending on the type of orchestrator you'll have to perform slightly
|
@@ -169,29 +171,41 @@ class BaseOrchestrator(StackComponent, ABC):
|
|
169
171
|
self,
|
170
172
|
deployment: "PipelineDeploymentResponse",
|
171
173
|
stack: "Stack",
|
174
|
+
placeholder_run: Optional["PipelineRunResponse"] = None,
|
172
175
|
) -> Any:
|
173
176
|
"""Runs a pipeline on a stack.
|
174
177
|
|
175
178
|
Args:
|
176
179
|
deployment: The pipeline deployment.
|
177
180
|
stack: The stack on which to run the pipeline.
|
178
|
-
|
179
|
-
|
180
|
-
Orchestrator-specific return value.
|
181
|
+
placeholder_run: An optional placeholder run for the deployment.
|
182
|
+
This will be deleted in case the pipeline deployment failed.
|
181
183
|
"""
|
182
184
|
self._prepare_run(deployment=deployment)
|
183
185
|
|
184
186
|
environment = get_config_environment_vars(deployment=deployment)
|
185
187
|
|
186
188
|
try:
|
187
|
-
|
188
|
-
deployment=deployment,
|
189
|
-
|
189
|
+
if metadata_iterator := self.prepare_or_run_pipeline(
|
190
|
+
deployment=deployment,
|
191
|
+
stack=stack,
|
192
|
+
environment=environment,
|
193
|
+
):
|
194
|
+
for metadata_dict in metadata_iterator:
|
195
|
+
try:
|
196
|
+
if placeholder_run:
|
197
|
+
publish_pipeline_run_metadata(
|
198
|
+
pipeline_run_id=placeholder_run.id,
|
199
|
+
pipeline_run_metadata={self.id: metadata_dict},
|
200
|
+
)
|
201
|
+
except Exception as e:
|
202
|
+
logger.debug(
|
203
|
+
"Something went went wrong trying to publish the"
|
204
|
+
f"run metadata: {e}"
|
205
|
+
)
|
190
206
|
finally:
|
191
207
|
self._cleanup_run()
|
192
208
|
|
193
|
-
return result
|
194
|
-
|
195
209
|
def run_step(self, step: "Step") -> None:
|
196
210
|
"""Runs the given step.
|
197
211
|
|
@@ -239,6 +253,21 @@ class BaseOrchestrator(StackComponent, ABC):
|
|
239
253
|
"""Cleans up the active run."""
|
240
254
|
self._active_deployment = None
|
241
255
|
|
256
|
+
def fetch_status(self, run: "PipelineRunResponse") -> ExecutionStatus:
|
257
|
+
"""Refreshes the status of a specific pipeline run.
|
258
|
+
|
259
|
+
Args:
|
260
|
+
run: A pipeline run response to fetch its status.
|
261
|
+
|
262
|
+
Raises:
|
263
|
+
NotImplementedError: If any orchestrator inheriting from the base
|
264
|
+
class does not implement this logic.
|
265
|
+
"""
|
266
|
+
raise NotImplementedError(
|
267
|
+
"The fetch status functionality is not implemented for the "
|
268
|
+
f"'{self.__class__.__name__}' orchestrator."
|
269
|
+
)
|
270
|
+
|
242
271
|
|
243
272
|
class BaseOrchestratorFlavor(Flavor):
|
244
273
|
"""Base orchestrator flavor class."""
|
zenml/stack/stack.py
CHANGED
@@ -62,7 +62,11 @@ if TYPE_CHECKING:
|
|
62
62
|
from zenml.image_builders import BaseImageBuilder
|
63
63
|
from zenml.model_deployers import BaseModelDeployer
|
64
64
|
from zenml.model_registries import BaseModelRegistry
|
65
|
-
from zenml.models import
|
65
|
+
from zenml.models import (
|
66
|
+
PipelineDeploymentBase,
|
67
|
+
PipelineDeploymentResponse,
|
68
|
+
PipelineRunResponse,
|
69
|
+
)
|
66
70
|
from zenml.orchestrators import BaseOrchestrator
|
67
71
|
from zenml.stack import StackComponent
|
68
72
|
from zenml.step_operators import BaseStepOperator
|
@@ -826,16 +830,21 @@ class Stack:
|
|
826
830
|
def deploy_pipeline(
|
827
831
|
self,
|
828
832
|
deployment: "PipelineDeploymentResponse",
|
833
|
+
placeholder_run: Optional["PipelineRunResponse"] = None,
|
829
834
|
) -> Any:
|
830
835
|
"""Deploys a pipeline on this stack.
|
831
836
|
|
832
837
|
Args:
|
833
838
|
deployment: The pipeline deployment.
|
839
|
+
placeholder_run: An optional placeholder run for the deployment.
|
840
|
+
This will be deleted in case the pipeline deployment failed.
|
834
841
|
|
835
842
|
Returns:
|
836
843
|
The return value of the call to `orchestrator.run_pipeline(...)`.
|
837
844
|
"""
|
838
|
-
return self.orchestrator.run(
|
845
|
+
return self.orchestrator.run(
|
846
|
+
deployment=deployment, stack=self, placeholder_run=placeholder_run
|
847
|
+
)
|
839
848
|
|
840
849
|
def _get_active_components_for_step(
|
841
850
|
self, step_config: "StepConfiguration"
|
zenml/utils/env_utils.py
CHANGED
@@ -14,7 +14,16 @@
|
|
14
14
|
"""Utility functions for handling environment variables."""
|
15
15
|
|
16
16
|
import os
|
17
|
-
|
17
|
+
import re
|
18
|
+
from typing import Any, Dict, List, Match, Optional, TypeVar, cast
|
19
|
+
|
20
|
+
from zenml.logger import get_logger
|
21
|
+
from zenml.utils import string_utils
|
22
|
+
|
23
|
+
logger = get_logger(__name__)
|
24
|
+
|
25
|
+
V = TypeVar("V", bound=Any)
|
26
|
+
ENV_VARIABLE_PLACEHOLDER_PATTERN = re.compile(pattern=r"\$\{([a-zA-Z0-9_]+)\}")
|
18
27
|
|
19
28
|
ENV_VAR_CHUNK_SUFFIX = "_CHUNK_"
|
20
29
|
|
@@ -99,3 +108,47 @@ def reconstruct_environment_variables(
|
|
99
108
|
# Remove the chunk environment variables
|
100
109
|
for key in chunk_keys:
|
101
110
|
env.pop(key)
|
111
|
+
|
112
|
+
|
113
|
+
def substitute_env_variable_placeholders(
|
114
|
+
value: V, raise_when_missing: bool = True
|
115
|
+
) -> V:
|
116
|
+
"""Substitute environment variable placeholders in an object.
|
117
|
+
|
118
|
+
Args:
|
119
|
+
value: The object in which to substitute the placeholders.
|
120
|
+
raise_when_missing: If True, an exception will be raised when an
|
121
|
+
environment variable is missing. Otherwise, a warning will be logged
|
122
|
+
instead.
|
123
|
+
|
124
|
+
Returns:
|
125
|
+
The object with placeholders substituted.
|
126
|
+
"""
|
127
|
+
|
128
|
+
def _replace_with_env_variable_value(match: Match[str]) -> str:
|
129
|
+
key = match.group(1)
|
130
|
+
if key in os.environ:
|
131
|
+
return os.environ[key]
|
132
|
+
else:
|
133
|
+
if raise_when_missing:
|
134
|
+
raise KeyError(
|
135
|
+
"Unable to substitute environment variable placeholder "
|
136
|
+
f"'{key}' because the environment variable is not set."
|
137
|
+
)
|
138
|
+
else:
|
139
|
+
logger.warning(
|
140
|
+
"Unable to substitute environment variable placeholder %s "
|
141
|
+
"because the environment variable is not set, using an "
|
142
|
+
"empty string instead.",
|
143
|
+
key,
|
144
|
+
)
|
145
|
+
return ""
|
146
|
+
|
147
|
+
def _substitution_func(v: str) -> str:
|
148
|
+
return ENV_VARIABLE_PLACEHOLDER_PATTERN.sub(
|
149
|
+
_replace_with_env_variable_value, v
|
150
|
+
)
|
151
|
+
|
152
|
+
return string_utils.substitute_string(
|
153
|
+
value=value, substitution_func=_substitution_func
|
154
|
+
)
|