zenml-nightly 0.75.0.dev20250318__py3-none-any.whl → 0.80.0.dev20250321__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/__init__.py +3 -1
- zenml/artifacts/artifact_config.py +2 -2
- zenml/artifacts/utils.py +4 -8
- zenml/cli/__init__.py +6 -6
- zenml/cli/base.py +2 -2
- zenml/cli/login.py +2 -2
- zenml/cli/server.py +6 -4
- zenml/cli/utils.py +3 -3
- zenml/client.py +9 -9
- zenml/config/compiler.py +1 -1
- zenml/config/server_config.py +1 -1
- zenml/constants.py +2 -1
- zenml/enums.py +12 -0
- zenml/integrations/airflow/__init__.py +0 -2
- zenml/integrations/argilla/__init__.py +0 -1
- zenml/integrations/aws/__init__.py +0 -3
- zenml/integrations/azure/__init__.py +0 -2
- zenml/integrations/azure/service_connectors/azure_service_connector.py +1 -1
- zenml/integrations/bentoml/__init__.py +0 -2
- zenml/integrations/bentoml/services/bentoml_container_deployment.py +2 -2
- zenml/integrations/bentoml/services/bentoml_local_deployment.py +1 -1
- zenml/integrations/bentoml/steps/bentoml_deployer.py +1 -1
- zenml/integrations/bitbucket/__init__.py +0 -2
- zenml/integrations/comet/__init__.py +0 -2
- zenml/integrations/databricks/__init__.py +0 -2
- zenml/integrations/databricks/services/databricks_deployment.py +3 -1
- zenml/integrations/deepchecks/__init__.py +0 -2
- zenml/integrations/discord/__init__.py +0 -2
- zenml/integrations/evidently/__init__.py +0 -2
- zenml/integrations/facets/__init__.py +0 -2
- zenml/integrations/feast/__init__.py +0 -2
- zenml/integrations/gcp/__init__.py +0 -3
- zenml/integrations/github/__init__.py +0 -2
- zenml/integrations/github/code_repositories/github_code_repository.py +7 -2
- zenml/integrations/gitlab/__init__.py +0 -1
- zenml/integrations/gitlab/code_repositories/gitlab_code_repository.py +5 -2
- zenml/integrations/great_expectations/__init__.py +0 -3
- zenml/integrations/huggingface/__init__.py +0 -1
- zenml/integrations/huggingface/services/huggingface_deployment.py +3 -1
- zenml/integrations/hyperai/__init__.py +0 -2
- zenml/integrations/kaniko/__init__.py +0 -2
- zenml/integrations/kubeflow/__init__.py +0 -1
- zenml/integrations/kubernetes/__init__.py +0 -2
- zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +4 -0
- zenml/integrations/kubernetes/orchestrators/kube_utils.py +89 -1
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +82 -48
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +44 -10
- zenml/integrations/kubernetes/orchestrators/manifest_utils.py +33 -1
- zenml/integrations/label_studio/__init__.py +0 -2
- zenml/integrations/langchain/__init__.py +0 -2
- zenml/integrations/lightgbm/__init__.py +0 -1
- zenml/integrations/lightning/__init__.py +0 -2
- zenml/integrations/mlflow/__init__.py +1 -3
- zenml/integrations/mlflow/services/mlflow_deployment.py +1 -1
- zenml/integrations/modal/__init__.py +0 -1
- zenml/integrations/neptune/__init__.py +0 -2
- zenml/integrations/neural_prophet/__init__.py +0 -2
- zenml/integrations/numpy/__init__.py +0 -2
- zenml/integrations/openai/__init__.py +0 -1
- zenml/integrations/pandas/__init__.py +0 -2
- zenml/integrations/pigeon/__init__.py +0 -1
- zenml/integrations/pillow/__init__.py +0 -3
- zenml/integrations/polars/__init__.py +0 -2
- zenml/integrations/prodigy/__init__.py +0 -1
- zenml/integrations/pycaret/__init__.py +0 -2
- zenml/integrations/pytorch/__init__.py +0 -1
- zenml/integrations/pytorch_lightning/__init__.py +0 -2
- zenml/integrations/s3/__init__.py +0 -2
- zenml/integrations/scipy/__init__.py +0 -2
- zenml/integrations/seldon/__init__.py +0 -2
- zenml/integrations/seldon/services/seldon_deployment.py +3 -2
- zenml/integrations/sklearn/__init__.py +1 -1
- zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +43 -18
- zenml/integrations/skypilot_aws/__init__.py +1 -3
- zenml/integrations/skypilot_azure/__init__.py +1 -2
- zenml/integrations/skypilot_gcp/__init__.py +1 -3
- zenml/integrations/skypilot_kubernetes/__init__.py +1 -3
- zenml/integrations/skypilot_lambda/__init__.py +1 -3
- zenml/integrations/slack/__init__.py +0 -1
- zenml/integrations/spark/__init__.py +0 -1
- zenml/integrations/tekton/__init__.py +0 -1
- zenml/integrations/tensorboard/__init__.py +0 -2
- zenml/integrations/tensorboard/services/tensorboard_service.py +1 -1
- zenml/integrations/tensorflow/__init__.py +0 -2
- zenml/integrations/vllm/__init__.py +0 -1
- zenml/integrations/vllm/services/vllm_deployment.py +1 -1
- zenml/integrations/wandb/__init__.py +0 -1
- zenml/integrations/whylogs/__init__.py +0 -1
- zenml/integrations/xgboost/__init__.py +0 -2
- zenml/login/credentials.py +1 -1
- zenml/materializers/__init__.py +1 -0
- zenml/model_deployers/base_model_deployer.py +1 -1
- zenml/models/__init__.py +4 -0
- zenml/models/v2/base/filter.py +162 -54
- zenml/models/v2/base/scoped.py +132 -0
- zenml/models/v2/core/artifact_version.py +12 -33
- zenml/models/v2/core/model_version.py +12 -50
- zenml/models/v2/core/pipeline_run.py +12 -32
- zenml/models/v2/core/service.py +2 -2
- zenml/models/v2/core/step_run.py +15 -32
- zenml/{services/service_type.py → models/v2/misc/service.py} +1 -1
- zenml/orchestrators/step_run_utils.py +1 -1
- zenml/orchestrators/utils.py +1 -1
- zenml/services/__init__.py +3 -5
- zenml/services/container/container_service.py +2 -1
- zenml/services/local/local_service.py +2 -1
- zenml/services/service.py +3 -2
- zenml/services/service_endpoint.py +2 -1
- zenml/services/service_monitor.py +1 -1
- zenml/services/service_status.py +1 -12
- zenml/steps/entrypoint_function_utils.py +1 -1
- zenml/utils/dashboard_utils.py +73 -8
- zenml/utils/server_utils.py +52 -0
- zenml/zen_server/dashboard/assets/{404-BbAvjc7Z.js → 404-2I8egBQu.js} +1 -1
- zenml/zen_server/dashboard/assets/@reactflow-BHoFKFSZ.js +17 -0
- zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-XL2NfFgP.js → AlertDialogDropdownItem-D7KZcPFw.js} +1 -1
- zenml/zen_server/dashboard/assets/CodeSnippet-DUkCnBpQ.js +9 -0
- zenml/zen_server/dashboard/assets/{CollapsibleCard-Djtd_ocf.js → CollapsibleCard-B5-5Plnd.js} +1 -1
- zenml/zen_server/dashboard/assets/{Commands-V-hH_IKQ.js → Commands-CbOMmarC.js} +1 -1
- zenml/zen_server/dashboard/assets/{ComponentBadge-CVN2FsiW.js → ComponentBadge-FrujKBC6.js} +1 -1
- zenml/zen_server/dashboard/assets/ComponentIcon-Dx5fBrDX.js +1 -0
- zenml/zen_server/dashboard/assets/{CsvVizualization-CWaQcWIN.js → CsvVizualization-B8E3p9we.js} +1 -1
- zenml/zen_server/dashboard/assets/{DeleteAlertDialog-CTLRrcFM.js → DeleteAlertDialog-BgTZbbAt.js} +1 -1
- zenml/zen_server/dashboard/assets/{DialogItem-ST291Hsl.js → DialogItem-CNWLiJcc.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-CIBjAdSc.js → Error-BkUP4Luv.js} +1 -1
- zenml/zen_server/dashboard/assets/ExecutionStatus-CD8Vj7sp.js +1 -0
- zenml/zen_server/dashboard/assets/{Helpbox-cwQNH06F.js → Helpbox-DIx6mDOH.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-DYKoAVhW.js → Infobox-BHEdNmME.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-Bk4QLPTU.js → InlineAvatar-Bin9UPKJ.js} +1 -1
- zenml/zen_server/dashboard/assets/{NestedCollapsible-CE4OF670.js → NestedCollapsible-Da-k0Mff.js} +1 -1
- zenml/zen_server/dashboard/assets/{Partials-cL1-u_sT.js → Partials-TNaYjHsV.js} +1 -1
- zenml/zen_server/dashboard/assets/ProBadge-BfPp-B97.js +1 -0
- zenml/zen_server/dashboard/assets/{ProCta-DtUutIul.js → ProCta-7_FtpX3I.js} +1 -1
- zenml/zen_server/dashboard/assets/ProviderIcon-CxeziA5a.js +1 -0
- zenml/zen_server/dashboard/assets/{ProviderRadio-C4bltH6-.js → ProviderRadio-DPmZHff_.js} +1 -1
- zenml/zen_server/dashboard/assets/RunSelector-BVKB4Z8F.js +1 -0
- zenml/zen_server/dashboard/assets/{RunsBody-D2VoO-cR.js → RunsBody-Cj4sIqQB.js} +1 -1
- zenml/zen_server/dashboard/assets/{SearchField-DfNxVtjV.js → SearchField-DjAOZic5.js} +1 -1
- zenml/zen_server/dashboard/assets/SecretTooltip-mMAAP4dM.js +1 -0
- zenml/zen_server/dashboard/assets/{SetPassword-CWl2mwz8.js → SetPassword-B0o5kSJU.js} +1 -1
- zenml/zen_server/dashboard/assets/{StackList-C8KNd00o.js → StackList-5UB8LoEq.js} +1 -1
- zenml/zen_server/dashboard/assets/{Tabs-BEWDPvPV.js → Tabs-AuhCyzle.js} +1 -1
- zenml/zen_server/dashboard/assets/Tick-CHW0jc8Y.js +1 -0
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DCuCj7NK.js → UpdatePasswordSchemas-Bauivjf-.js} +1 -1
- zenml/zen_server/dashboard/assets/{UsageReason-CwUrEwEz.js → UsageReason-Dr5ca5M4.js} +1 -1
- zenml/zen_server/dashboard/assets/{Wizard-CynnoHg4.js → Wizard-XEp9rGmf.js} +1 -1
- zenml/zen_server/dashboard/assets/{WizardFooter-B2bYs89C.js → WizardFooter-BtL1Gi1k.js} +1 -1
- zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-B509kMlL.js → all-pipeline-runs-query-COvsm3bC.js} +1 -1
- zenml/zen_server/dashboard/assets/configuration-form-BJUCr0wl.js +1 -0
- zenml/zen_server/dashboard/assets/{create-stack-BjWXz5nx.js → create-stack-B2c98UlP.js} +1 -1
- zenml/zen_server/dashboard/assets/{delete-run-CzPWbsBy.js → delete-run-Do3XyF4W.js} +1 -1
- zenml/zen_server/dashboard/assets/flavor-select-D8CranSY.js +1 -0
- zenml/zen_server/dashboard/assets/{form-schemas-B6u3P_a4.js → form-schemas-Bm-dTV3L.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-BCKg1Y5r.css → index-6mLFgFwe.css} +1 -1
- zenml/zen_server/dashboard/assets/{index-Bjeu4_0O.js → index-CzhJC6pc.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-CaRx22lH.js → index-D-n6tspq.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-DWoLoYDY.js → index-DPjvk73v.js} +8 -8
- zenml/zen_server/dashboard/assets/{index-Dba8yULY.js → index-eIIP-0dQ.js} +1 -1
- zenml/zen_server/dashboard/assets/login-mutation-D6uiKsKk.js +1 -0
- zenml/zen_server/dashboard/assets/{not-found-DGQ8rm7B.js → not-found-DFrksY0r.js} +1 -1
- zenml/zen_server/dashboard/assets/page-B-uHUFcm.js +1 -0
- zenml/zen_server/dashboard/assets/page-B0Llmzo_.js +1 -0
- zenml/zen_server/dashboard/assets/page-B150LbzG.js +1 -0
- zenml/zen_server/dashboard/assets/{page-CfeQbejg.js → page-B1Un9vAU.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CxrLV30P.js → page-B80TE04v.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BIseZTJt.js +2 -0
- zenml/zen_server/dashboard/assets/{page-C5xq6rqE.js → page-BJ15SGwt.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-B6msmF1h.js → page-BJrZsPSh.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BMZaECzB.js +1 -0
- zenml/zen_server/dashboard/assets/{page-D1upvSPi.js → page-BTvnIFGR.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DLw1Apss.js → page-BXh1mF-D.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BZUxCBoD.js +1 -0
- zenml/zen_server/dashboard/assets/page-BeFiRx31.js +1 -0
- zenml/zen_server/dashboard/assets/{page-C89bN6VV.js → page-BnUwQBeg.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-k-UXKVnV.js → page-BqQ6y8Hb.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BwAFqFCf.js +1 -0
- zenml/zen_server/dashboard/assets/page-BzlVs5tC.js +1 -0
- zenml/zen_server/dashboard/assets/{page-C3BbJ-5n.js → page-C11vPVkH.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-AnG2ilmi.js → page-CAKBSE9f.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CPe9nQSo.js +1 -0
- zenml/zen_server/dashboard/assets/page-D0Zt2-7X.js +1 -0
- zenml/zen_server/dashboard/assets/page-D2F0Rvak.js +1 -0
- zenml/zen_server/dashboard/assets/{page-2EzZ5aWS.js → page-D5GZlpKq.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CxoG4zme.js → page-DBNBYSwq.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DDvwWgKP.js +6 -0
- zenml/zen_server/dashboard/assets/page-DF9q7ySu.js +1 -0
- zenml/zen_server/dashboard/assets/page-DOzFoJuo.js +1 -0
- zenml/zen_server/dashboard/assets/page-DaHH2ZEF.js +1 -0
- zenml/zen_server/dashboard/assets/{page-B9ELcPAy.js → page-Dd-0y3SU.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Dy6HYsJr.js → page-DhNnHHmX.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CZ_3LB0U.js → page-DkJfgcDi.js} +1 -1
- zenml/zen_server/dashboard/assets/page-EhqRFAZc.js +1 -0
- zenml/zen_server/dashboard/assets/{page-nHAZvd76.js → page-NIWnUdVg.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DazwBcbq.js → page-kYlFrH53.js} +1 -1
- zenml/zen_server/dashboard/assets/page-ygCPGHAV.js +1 -0
- zenml/zen_server/dashboard/assets/{persist-BglceT_t.js → persist-C5RlwSq6.js} +1 -1
- zenml/zen_server/dashboard/assets/{persist-CMkLV2Cs.js → persist-DHGuHP2H.js} +1 -1
- zenml/zen_server/dashboard/assets/{service-DNKY_ZYd.js → service-Do7yitqe.js} +1 -1
- zenml/zen_server/dashboard/assets/{sharedSchema-BOmQa793.js → sharedSchema-i_9Y4WcA.js} +1 -1
- zenml/zen_server/dashboard/assets/stack-detail-query-omCumL7U.js +1 -0
- zenml/zen_server/dashboard/assets/update-server-settings-mutation-B4eE33z-.js +1 -0
- zenml/zen_server/dashboard/index.html +4 -4
- zenml/zen_server/deploy/daemon/daemon_zen_server.py +1 -1
- zenml/zen_server/deploy/deployment.py +1 -2
- zenml/zen_server/deploy/docker/docker_zen_server.py +1 -1
- zenml/zen_server/rbac/endpoint_utils.py +1 -2
- zenml/zen_server/routers/projects_endpoints.py +14 -3
- zenml/zen_server/utils.py +2 -86
- zenml/zen_stores/migrations/versions/0.80.0_release.py +23 -0
- zenml/zen_stores/schemas/artifact_visualization_schemas.py +1 -1
- zenml/zen_stores/schemas/model_schemas.py +1 -1
- zenml/zen_stores/schemas/service_schemas.py +1 -1
- zenml/zen_stores/schemas/step_run_schemas.py +1 -1
- zenml/zen_stores/schemas/trigger_schemas.py +1 -1
- zenml/zen_stores/sql_zen_store.py +5 -0
- {zenml_nightly-0.75.0.dev20250318.dist-info → zenml_nightly-0.80.0.dev20250321.dist-info}/METADATA +2 -2
- {zenml_nightly-0.75.0.dev20250318.dist-info → zenml_nightly-0.80.0.dev20250321.dist-info}/RECORD +221 -220
- zenml/zen_server/dashboard/assets/@reactflow-DMaYqp8l.js +0 -17
- zenml/zen_server/dashboard/assets/CodeSnippet-D8ptwPjg.js +0 -9
- zenml/zen_server/dashboard/assets/ComponentIcon-gpMJ2Y2e.js +0 -1
- zenml/zen_server/dashboard/assets/ExecutionStatus-DHiK3Am-.js +0 -1
- zenml/zen_server/dashboard/assets/ProBadge-ypma7R8i.js +0 -1
- zenml/zen_server/dashboard/assets/ProviderIcon-DKN3Gdcg.js +0 -1
- zenml/zen_server/dashboard/assets/RunSelector-CYmRHGdm.js +0 -1
- zenml/zen_server/dashboard/assets/SecretTooltip-CHPWF0bu.js +0 -1
- zenml/zen_server/dashboard/assets/Tick-DgU4udUn.js +0 -1
- zenml/zen_server/dashboard/assets/configuration-form-BEwWCxqY.js +0 -1
- zenml/zen_server/dashboard/assets/flavor-select-C1pyy8gq.js +0 -1
- zenml/zen_server/dashboard/assets/login-mutation-7WFxPe10.js +0 -1
- zenml/zen_server/dashboard/assets/page-BKN4SYXY.js +0 -1
- zenml/zen_server/dashboard/assets/page-BNrOW_3T.js +0 -2
- zenml/zen_server/dashboard/assets/page-BX6ZrAVH.js +0 -1
- zenml/zen_server/dashboard/assets/page-BnOdORy3.js +0 -1
- zenml/zen_server/dashboard/assets/page-BtkfcEI7.js +0 -1
- zenml/zen_server/dashboard/assets/page-Bz_grLBY.js +0 -1
- zenml/zen_server/dashboard/assets/page-CCEwuGU4.js +0 -1
- zenml/zen_server/dashboard/assets/page-COAGXWJu.js +0 -1
- zenml/zen_server/dashboard/assets/page-CaibMa0l.js +0 -1
- zenml/zen_server/dashboard/assets/page-CskoTYOC.js +0 -1
- zenml/zen_server/dashboard/assets/page-Cyoe7AtN.js +0 -1
- zenml/zen_server/dashboard/assets/page-D03wm5f1.js +0 -1
- zenml/zen_server/dashboard/assets/page-D8UimvyP.js +0 -1
- zenml/zen_server/dashboard/assets/page-DEnmFyzi.js +0 -1
- zenml/zen_server/dashboard/assets/page-TiOZeeo0.js +0 -1
- zenml/zen_server/dashboard/assets/page-cveasWUr.js +0 -6
- zenml/zen_server/dashboard/assets/page-iTvxfhgZ.js +0 -1
- zenml/zen_server/dashboard/assets/page-niRD8Hqz.js +0 -1
- zenml/zen_server/dashboard/assets/stack-detail-query-CI_YMUx6.js +0 -1
- zenml/zen_server/dashboard/assets/transform-DKsRLKTv.js +0 -1
- zenml/zen_server/dashboard/assets/update-server-settings-mutation-CNYCc-FU.js +0 -1
- {zenml_nightly-0.75.0.dev20250318.dist-info → zenml_nightly-0.80.0.dev20250321.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.75.0.dev20250318.dist-info → zenml_nightly-0.80.0.dev20250321.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.75.0.dev20250318.dist-info → zenml_nightly-0.80.0.dev20250321.dist-info}/entry_points.txt +0 -0
@@ -85,6 +85,9 @@ class KubernetesOrchestratorConfig(
|
|
85
85
|
parallel_step_startup_waiting_period: How long to wait in between
|
86
86
|
starting parallel steps. This can be used to distribute server
|
87
87
|
load when running pipelines with a huge amount of parallel steps.
|
88
|
+
pass_zenml_token_as_secret: If `True`, the ZenML token will be passed
|
89
|
+
as a Kubernetes secret to the pods. For this to work, the Kubernetes
|
90
|
+
client must have permissions to create secrets in the namespace.
|
88
91
|
"""
|
89
92
|
|
90
93
|
incluster: bool = False
|
@@ -93,6 +96,7 @@ class KubernetesOrchestratorConfig(
|
|
93
96
|
local: bool = False
|
94
97
|
skip_local_validations: bool = False
|
95
98
|
parallel_step_startup_waiting_period: Optional[float] = None
|
99
|
+
pass_zenml_token_as_secret: bool = False
|
96
100
|
|
97
101
|
@property
|
98
102
|
def is_remote(self) -> bool:
|
@@ -34,7 +34,7 @@ Adjusted from https://github.com/tensorflow/tfx/blob/master/tfx/utils/kube_utils
|
|
34
34
|
import enum
|
35
35
|
import re
|
36
36
|
import time
|
37
|
-
from typing import Any, Callable, Optional, TypeVar, cast
|
37
|
+
from typing import Any, Callable, Dict, Optional, TypeVar, cast
|
38
38
|
|
39
39
|
from kubernetes import client as k8s_client
|
40
40
|
from kubernetes import config as k8s_config
|
@@ -43,6 +43,7 @@ from kubernetes.client.rest import ApiException
|
|
43
43
|
from zenml.integrations.kubernetes.orchestrators.manifest_utils import (
|
44
44
|
build_namespace_manifest,
|
45
45
|
build_role_binding_manifest_for_service_account,
|
46
|
+
build_secret_manifest,
|
46
47
|
build_service_account_manifest,
|
47
48
|
)
|
48
49
|
from zenml.logger import get_logger
|
@@ -371,3 +372,90 @@ def create_namespace(core_api: k8s_client.CoreV1Api, namespace: str) -> None:
|
|
371
372
|
"""
|
372
373
|
manifest = build_namespace_manifest(namespace)
|
373
374
|
_if_not_exists(core_api.create_namespace)(body=manifest)
|
375
|
+
|
376
|
+
|
377
|
+
def create_secret(
|
378
|
+
core_api: k8s_client.CoreV1Api,
|
379
|
+
namespace: str,
|
380
|
+
secret_name: str,
|
381
|
+
data: Dict[str, Optional[str]],
|
382
|
+
) -> None:
|
383
|
+
"""Create a Kubernetes secret.
|
384
|
+
|
385
|
+
Args:
|
386
|
+
core_api: Client of Core V1 API of Kubernetes API.
|
387
|
+
namespace: The namespace in which to create the secret.
|
388
|
+
secret_name: The name of the secret to create.
|
389
|
+
data: The secret data.
|
390
|
+
"""
|
391
|
+
core_api.create_namespaced_secret(
|
392
|
+
namespace=namespace,
|
393
|
+
body=build_secret_manifest(name=secret_name, data=data),
|
394
|
+
)
|
395
|
+
|
396
|
+
|
397
|
+
def update_secret(
|
398
|
+
core_api: k8s_client.CoreV1Api,
|
399
|
+
namespace: str,
|
400
|
+
secret_name: str,
|
401
|
+
data: Dict[str, Optional[str]],
|
402
|
+
) -> None:
|
403
|
+
"""Update a Kubernetes secret.
|
404
|
+
|
405
|
+
Args:
|
406
|
+
core_api: Client of Core V1 API of Kubernetes API.
|
407
|
+
namespace: The namespace in which to update the secret.
|
408
|
+
secret_name: The name of the secret to update.
|
409
|
+
data: The secret data. If the value is None, the key will be removed
|
410
|
+
from the secret.
|
411
|
+
"""
|
412
|
+
core_api.patch_namespaced_secret(
|
413
|
+
namespace=namespace,
|
414
|
+
name=secret_name,
|
415
|
+
body=build_secret_manifest(name=secret_name, data=data),
|
416
|
+
)
|
417
|
+
|
418
|
+
|
419
|
+
def create_or_update_secret(
|
420
|
+
core_api: k8s_client.CoreV1Api,
|
421
|
+
namespace: str,
|
422
|
+
secret_name: str,
|
423
|
+
data: Dict[str, Optional[str]],
|
424
|
+
) -> None:
|
425
|
+
"""Create a Kubernetes secret if it doesn't exist, or update it if it does.
|
426
|
+
|
427
|
+
Args:
|
428
|
+
core_api: Client of Core V1 API of Kubernetes API.
|
429
|
+
namespace: The namespace in which to create or update the secret.
|
430
|
+
secret_name: The name of the secret to create or update.
|
431
|
+
data: The secret data. If the value is None, the key will be removed
|
432
|
+
from the secret.
|
433
|
+
|
434
|
+
Raises:
|
435
|
+
ApiException: If the secret creation failed for any reason other than
|
436
|
+
the secret already existing.
|
437
|
+
"""
|
438
|
+
try:
|
439
|
+
create_secret(core_api, namespace, secret_name, data)
|
440
|
+
except ApiException as e:
|
441
|
+
if e.status != 409:
|
442
|
+
raise
|
443
|
+
update_secret(core_api, namespace, secret_name, data)
|
444
|
+
|
445
|
+
|
446
|
+
def delete_secret(
|
447
|
+
core_api: k8s_client.CoreV1Api,
|
448
|
+
namespace: str,
|
449
|
+
secret_name: str,
|
450
|
+
) -> None:
|
451
|
+
"""Delete a Kubernetes secret.
|
452
|
+
|
453
|
+
Args:
|
454
|
+
core_api: Client of Core V1 API of Kubernetes API.
|
455
|
+
namespace: The namespace in which to delete the secret.
|
456
|
+
secret_name: The name of the secret to delete.
|
457
|
+
"""
|
458
|
+
core_api.delete_namespaced_secret(
|
459
|
+
name=secret_name,
|
460
|
+
namespace=namespace,
|
461
|
+
)
|
@@ -41,6 +41,7 @@ from typing import (
|
|
41
41
|
Type,
|
42
42
|
cast,
|
43
43
|
)
|
44
|
+
from uuid import UUID
|
44
45
|
|
45
46
|
from kubernetes import client as k8s_client
|
46
47
|
from kubernetes import config as k8s_config
|
@@ -72,6 +73,7 @@ if TYPE_CHECKING:
|
|
72
73
|
logger = get_logger(__name__)
|
73
74
|
|
74
75
|
ENV_ZENML_KUBERNETES_RUN_ID = "ZENML_KUBERNETES_RUN_ID"
|
76
|
+
KUBERNETES_SECRET_TOKEN_KEY_NAME = "zenml_api_token"
|
75
77
|
|
76
78
|
|
77
79
|
class KubernetesOrchestrator(ContainerizedOrchestrator):
|
@@ -368,6 +370,17 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
368
370
|
|
369
371
|
return pod_settings
|
370
372
|
|
373
|
+
def get_token_secret_name(self, deployment_id: UUID) -> str:
|
374
|
+
"""Returns the name of the secret that contains the ZenML token.
|
375
|
+
|
376
|
+
Args:
|
377
|
+
deployment_id: The ID of the deployment.
|
378
|
+
|
379
|
+
Returns:
|
380
|
+
The name of the secret that contains the ZenML token.
|
381
|
+
"""
|
382
|
+
return f"zenml-token-{deployment_id}"
|
383
|
+
|
371
384
|
def prepare_or_run_pipeline(
|
372
385
|
self,
|
373
386
|
deployment: "PipelineDeploymentResponse",
|
@@ -439,6 +452,38 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
439
452
|
# Authorize pod to run Kubernetes commands inside the cluster.
|
440
453
|
service_account_name = self._get_service_account_name(settings)
|
441
454
|
|
455
|
+
# We set some default minimum resource requests for the orchestrator pod
|
456
|
+
# here if the user has not specified any, because the orchestrator pod
|
457
|
+
# takes up some memory resources itself and, if not specified, the pod
|
458
|
+
# will be scheduled on any node regardless of available memory and risk
|
459
|
+
# negatively impacting or even crashing the node due to memory pressure.
|
460
|
+
orchestrator_pod_settings = self.apply_default_resource_requests(
|
461
|
+
memory="400Mi",
|
462
|
+
cpu="100m",
|
463
|
+
pod_settings=settings.orchestrator_pod_settings,
|
464
|
+
)
|
465
|
+
|
466
|
+
if self.config.pass_zenml_token_as_secret:
|
467
|
+
secret_name = self.get_token_secret_name(deployment.id)
|
468
|
+
token = environment.pop("ZENML_STORE_API_TOKEN")
|
469
|
+
kube_utils.create_or_update_secret(
|
470
|
+
core_api=self._k8s_core_api,
|
471
|
+
namespace=self.config.kubernetes_namespace,
|
472
|
+
secret_name=secret_name,
|
473
|
+
data={KUBERNETES_SECRET_TOKEN_KEY_NAME: token},
|
474
|
+
)
|
475
|
+
orchestrator_pod_settings.env.append(
|
476
|
+
{
|
477
|
+
"name": "ZENML_STORE_API_TOKEN",
|
478
|
+
"valueFrom": {
|
479
|
+
"secretKeyRef": {
|
480
|
+
"name": secret_name,
|
481
|
+
"key": KUBERNETES_SECRET_TOKEN_KEY_NAME,
|
482
|
+
}
|
483
|
+
},
|
484
|
+
}
|
485
|
+
)
|
486
|
+
|
442
487
|
# Schedule as CRON job if CRON schedule is given.
|
443
488
|
if deployment.schedule:
|
444
489
|
if not deployment.schedule.cron_expression:
|
@@ -458,7 +503,7 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
458
503
|
args=args,
|
459
504
|
service_account_name=service_account_name,
|
460
505
|
privileged=False,
|
461
|
-
pod_settings=
|
506
|
+
pod_settings=orchestrator_pod_settings,
|
462
507
|
env=environment,
|
463
508
|
mount_local_stores=self.config.is_local,
|
464
509
|
)
|
@@ -472,57 +517,46 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
472
517
|
f'`"{cron_expression}"`.'
|
473
518
|
)
|
474
519
|
return
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
# will be scheduled on any node regardless of available memory and risk
|
480
|
-
# negatively impacting or even crashing the node due to memory pressure.
|
481
|
-
orchestrator_pod_settings = self.apply_default_resource_requests(
|
482
|
-
memory="400Mi",
|
483
|
-
cpu="100m",
|
484
|
-
pod_settings=settings.orchestrator_pod_settings,
|
485
|
-
)
|
486
|
-
|
487
|
-
# Create and run the orchestrator pod.
|
488
|
-
pod_manifest = build_pod_manifest(
|
489
|
-
run_name=orchestrator_run_name,
|
490
|
-
pod_name=pod_name,
|
491
|
-
pipeline_name=pipeline_name,
|
492
|
-
image_name=image,
|
493
|
-
command=command,
|
494
|
-
args=args,
|
495
|
-
privileged=False,
|
496
|
-
pod_settings=orchestrator_pod_settings,
|
497
|
-
service_account_name=service_account_name,
|
498
|
-
env=environment,
|
499
|
-
mount_local_stores=self.config.is_local,
|
500
|
-
)
|
501
|
-
|
502
|
-
self._k8s_core_api.create_namespaced_pod(
|
503
|
-
namespace=self.config.kubernetes_namespace,
|
504
|
-
body=pod_manifest,
|
505
|
-
)
|
506
|
-
|
507
|
-
# Wait for the orchestrator pod to finish and stream logs.
|
508
|
-
if settings.synchronous:
|
509
|
-
logger.info("Waiting for Kubernetes orchestrator pod...")
|
510
|
-
kube_utils.wait_pod(
|
511
|
-
kube_client_fn=self.get_kube_client,
|
520
|
+
else:
|
521
|
+
# Create and run the orchestrator pod.
|
522
|
+
pod_manifest = build_pod_manifest(
|
523
|
+
run_name=orchestrator_run_name,
|
512
524
|
pod_name=pod_name,
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
525
|
+
pipeline_name=pipeline_name,
|
526
|
+
image_name=image,
|
527
|
+
command=command,
|
528
|
+
args=args,
|
529
|
+
privileged=False,
|
530
|
+
pod_settings=orchestrator_pod_settings,
|
531
|
+
service_account_name=service_account_name,
|
532
|
+
env=environment,
|
533
|
+
mount_local_stores=self.config.is_local,
|
517
534
|
)
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
f"Run the following command to inspect the logs: "
|
523
|
-
f"`kubectl logs {pod_name} -n {self.config.kubernetes_namespace}`."
|
535
|
+
|
536
|
+
self._k8s_core_api.create_namespaced_pod(
|
537
|
+
namespace=self.config.kubernetes_namespace,
|
538
|
+
body=pod_manifest,
|
524
539
|
)
|
525
540
|
|
541
|
+
# Wait for the orchestrator pod to finish and stream logs.
|
542
|
+
if settings.synchronous:
|
543
|
+
logger.info("Waiting for Kubernetes orchestrator pod...")
|
544
|
+
kube_utils.wait_pod(
|
545
|
+
kube_client_fn=self.get_kube_client,
|
546
|
+
pod_name=pod_name,
|
547
|
+
namespace=self.config.kubernetes_namespace,
|
548
|
+
exit_condition_lambda=kube_utils.pod_is_done,
|
549
|
+
timeout_sec=settings.timeout,
|
550
|
+
stream_logs=True,
|
551
|
+
)
|
552
|
+
else:
|
553
|
+
logger.info(
|
554
|
+
f"Orchestration started asynchronously in pod "
|
555
|
+
f"`{self.config.kubernetes_namespace}:{pod_name}`. "
|
556
|
+
f"Run the following command to inspect the logs: "
|
557
|
+
f"`kubectl logs {pod_name} -n {self.config.kubernetes_namespace}`."
|
558
|
+
)
|
559
|
+
|
526
560
|
def _get_service_account_name(
|
527
561
|
self, settings: KubernetesOrchestratorSettings
|
528
562
|
) -> str:
|
@@ -28,6 +28,7 @@ from zenml.integrations.kubernetes.flavors.kubernetes_orchestrator_flavor import
|
|
28
28
|
from zenml.integrations.kubernetes.orchestrators import kube_utils
|
29
29
|
from zenml.integrations.kubernetes.orchestrators.kubernetes_orchestrator import (
|
30
30
|
ENV_ZENML_KUBERNETES_RUN_ID,
|
31
|
+
KUBERNETES_SECRET_TOKEN_KEY_NAME,
|
31
32
|
KubernetesOrchestrator,
|
32
33
|
)
|
33
34
|
from zenml.integrations.kubernetes.orchestrators.manifest_utils import (
|
@@ -82,6 +83,9 @@ def main() -> None:
|
|
82
83
|
kube_client = orchestrator.get_kube_client(incluster=True)
|
83
84
|
core_api = k8s_client.CoreV1Api(kube_client)
|
84
85
|
|
86
|
+
env = get_config_environment_vars()
|
87
|
+
env[ENV_ZENML_KUBERNETES_RUN_ID] = orchestrator_run_id
|
88
|
+
|
85
89
|
def run_step_on_kubernetes(step_name: str) -> None:
|
86
90
|
"""Run a pipeline step in a separate Kubernetes pod.
|
87
91
|
|
@@ -115,9 +119,6 @@ def main() -> None:
|
|
115
119
|
orchestrator_settings
|
116
120
|
)
|
117
121
|
|
118
|
-
env = get_config_environment_vars()
|
119
|
-
env[ENV_ZENML_KUBERNETES_RUN_ID] = orchestrator_run_id
|
120
|
-
|
121
122
|
# We set some default minimum memory resource requests for the step pod
|
122
123
|
# here if the user has not specified any, because the step pod takes up
|
123
124
|
# some memory resources itself and, if not specified, the pod will be
|
@@ -128,6 +129,23 @@ def main() -> None:
|
|
128
129
|
pod_settings=settings.pod_settings,
|
129
130
|
)
|
130
131
|
|
132
|
+
if orchestrator.config.pass_zenml_token_as_secret:
|
133
|
+
env.pop("ZENML_STORE_API_TOKEN", None)
|
134
|
+
secret_name = orchestrator.get_token_secret_name(
|
135
|
+
deployment_config.id
|
136
|
+
)
|
137
|
+
pod_settings.env.append(
|
138
|
+
{
|
139
|
+
"name": "ZENML_STORE_API_TOKEN",
|
140
|
+
"valueFrom": {
|
141
|
+
"secretKeyRef": {
|
142
|
+
"name": secret_name,
|
143
|
+
"key": KUBERNETES_SECRET_TOKEN_KEY_NAME,
|
144
|
+
}
|
145
|
+
},
|
146
|
+
}
|
147
|
+
)
|
148
|
+
|
131
149
|
# Define Kubernetes pod manifest.
|
132
150
|
pod_manifest = build_pod_manifest(
|
133
151
|
pod_name=pod_name,
|
@@ -166,13 +184,29 @@ def main() -> None:
|
|
166
184
|
parallel_node_startup_waiting_period = (
|
167
185
|
orchestrator.config.parallel_step_startup_waiting_period or 0.0
|
168
186
|
)
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
187
|
+
try:
|
188
|
+
ThreadedDagRunner(
|
189
|
+
dag=pipeline_dag,
|
190
|
+
run_fn=run_step_on_kubernetes,
|
191
|
+
parallel_node_startup_waiting_period=parallel_node_startup_waiting_period,
|
192
|
+
).run()
|
193
|
+
logger.info("Orchestration pod completed.")
|
194
|
+
finally:
|
195
|
+
if (
|
196
|
+
orchestrator.config.pass_zenml_token_as_secret
|
197
|
+
and deployment_config.schedule is None
|
198
|
+
):
|
199
|
+
secret_name = orchestrator.get_token_secret_name(
|
200
|
+
deployment_config.id
|
201
|
+
)
|
202
|
+
try:
|
203
|
+
kube_utils.delete_secret(
|
204
|
+
core_api=core_api,
|
205
|
+
namespace=args.kubernetes_namespace,
|
206
|
+
secret_name=secret_name,
|
207
|
+
)
|
208
|
+
except k8s_client.rest.ApiException as e:
|
209
|
+
logger.error(f"Error cleaning up secret {secret_name}: {e}")
|
176
210
|
|
177
211
|
|
178
212
|
if __name__ == "__main__":
|
@@ -13,9 +13,10 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Utility functions for building manifests for k8s pods."""
|
15
15
|
|
16
|
+
import base64
|
16
17
|
import os
|
17
18
|
import sys
|
18
|
-
from typing import Any, Dict, List, Optional
|
19
|
+
from typing import Any, Dict, List, Mapping, Optional
|
19
20
|
|
20
21
|
from kubernetes import client as k8s_client
|
21
22
|
|
@@ -390,3 +391,34 @@ def build_namespace_manifest(namespace: str) -> Dict[str, Any]:
|
|
390
391
|
"name": namespace,
|
391
392
|
},
|
392
393
|
}
|
394
|
+
|
395
|
+
|
396
|
+
def build_secret_manifest(
|
397
|
+
name: str,
|
398
|
+
data: Mapping[str, Optional[str]],
|
399
|
+
secret_type: str = "Opaque",
|
400
|
+
) -> Dict[str, Any]:
|
401
|
+
"""Builds a Kubernetes secret manifest.
|
402
|
+
|
403
|
+
Args:
|
404
|
+
name: Name of the secret.
|
405
|
+
data: The secret data.
|
406
|
+
secret_type: The secret type.
|
407
|
+
|
408
|
+
Returns:
|
409
|
+
The secret manifest.
|
410
|
+
"""
|
411
|
+
encoded_data = {
|
412
|
+
key: base64.b64encode(value.encode()).decode() if value else None
|
413
|
+
for key, value in data.items()
|
414
|
+
}
|
415
|
+
|
416
|
+
return {
|
417
|
+
"apiVersion": "v1",
|
418
|
+
"kind": "Secret",
|
419
|
+
"metadata": {
|
420
|
+
"name": name,
|
421
|
+
},
|
422
|
+
"type": secret_type,
|
423
|
+
"data": encoded_data,
|
424
|
+
}
|
@@ -58,7 +58,7 @@ class MlflowIntegration(Integration):
|
|
58
58
|
from zenml.integrations.pandas import PandasIntegration
|
59
59
|
|
60
60
|
reqs = [
|
61
|
-
"mlflow>=2.1.1,<
|
61
|
+
"mlflow>=2.1.1,<2.21.0",
|
62
62
|
# TODO: remove this requirement once rapidjson is fixed
|
63
63
|
"python-rapidjson<1.15",
|
64
64
|
# When you do:
|
@@ -111,5 +111,3 @@ class MlflowIntegration(Integration):
|
|
111
111
|
MLFlowModelRegistryFlavor,
|
112
112
|
]
|
113
113
|
|
114
|
-
|
115
|
-
MlflowIntegration.check_installation()
|
@@ -30,6 +30,7 @@ from zenml.integrations.mlflow.experiment_trackers.mlflow_experiment_tracker imp
|
|
30
30
|
MLFlowExperimentTracker,
|
31
31
|
)
|
32
32
|
from zenml.logger import get_logger
|
33
|
+
from zenml.models.v2.misc.service import ServiceType
|
33
34
|
from zenml.services import (
|
34
35
|
HTTPEndpointHealthMonitor,
|
35
36
|
HTTPEndpointHealthMonitorConfig,
|
@@ -38,7 +39,6 @@ from zenml.services import (
|
|
38
39
|
LocalDaemonServiceEndpoint,
|
39
40
|
LocalDaemonServiceEndpointConfig,
|
40
41
|
ServiceEndpointProtocol,
|
41
|
-
ServiceType,
|
42
42
|
)
|
43
43
|
from zenml.services.service import BaseDeploymentService
|
44
44
|
|
@@ -22,6 +22,7 @@ import requests
|
|
22
22
|
from pydantic import Field, ValidationError
|
23
23
|
|
24
24
|
from zenml import __version__
|
25
|
+
from zenml.enums import ServiceState
|
25
26
|
from zenml.integrations.seldon.seldon_client import (
|
26
27
|
SeldonClient,
|
27
28
|
SeldonDeployment,
|
@@ -30,9 +31,9 @@ from zenml.integrations.seldon.seldon_client import (
|
|
30
31
|
SeldonResourceRequirements,
|
31
32
|
)
|
32
33
|
from zenml.logger import get_logger
|
34
|
+
from zenml.models.v2.misc.service import ServiceType
|
33
35
|
from zenml.services.service import BaseDeploymentService, ServiceConfig
|
34
|
-
from zenml.services.service_status import
|
35
|
-
from zenml.services.service_type import ServiceType
|
36
|
+
from zenml.services.service_status import ServiceStatus
|
36
37
|
|
37
38
|
logger = get_logger(__name__)
|
38
39
|
|