zenml-nightly 0.66.0.dev20240927__py3-none-any.whl → 0.68.1.dev20241102__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.
- README.md +18 -12
- RELEASE_NOTES.md +236 -0
- zenml/VERSION +1 -1
- zenml/__init__.py +5 -10
- zenml/analytics/context.py +16 -1
- zenml/analytics/enums.py +0 -13
- zenml/analytics/utils.py +18 -7
- zenml/artifact_stores/base_artifact_store.py +11 -0
- zenml/artifacts/artifact_config.py +19 -65
- zenml/artifacts/external_artifact.py +7 -53
- zenml/artifacts/external_artifact_config.py +21 -40
- zenml/artifacts/load_directory_materializer.py +91 -0
- zenml/artifacts/utils.py +204 -145
- zenml/cli/__init__.py +62 -127
- zenml/cli/base.py +8 -8
- zenml/cli/integration.py +0 -9
- zenml/cli/login.py +951 -0
- zenml/cli/pipeline.py +1 -1
- zenml/cli/served_model.py +8 -1
- zenml/cli/server.py +462 -577
- zenml/cli/service_accounts.py +4 -4
- zenml/cli/stack.py +78 -569
- zenml/cli/stack_components.py +5 -594
- zenml/cli/user_management.py +0 -12
- zenml/cli/utils.py +24 -142
- zenml/client.py +57 -40
- zenml/client_lazy_loader.py +29 -12
- zenml/config/compiler.py +7 -11
- zenml/config/global_config.py +9 -0
- zenml/config/pipeline_configurations.py +2 -1
- zenml/config/pipeline_run_configuration.py +2 -1
- zenml/config/server_config.py +7 -5
- zenml/config/step_configurations.py +2 -0
- zenml/constants.py +6 -42
- zenml/enums.py +1 -4
- zenml/environment.py +1 -315
- zenml/exceptions.py +12 -41
- zenml/hooks/hook_validators.py +1 -8
- zenml/integrations/airflow/orchestrators/airflow_orchestrator.py +2 -3
- zenml/integrations/argilla/__init__.py +1 -1
- zenml/integrations/argilla/annotators/argilla_annotator.py +234 -89
- zenml/integrations/argilla/flavors/argilla_annotator_flavor.py +10 -5
- zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py +9 -5
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +15 -2
- zenml/integrations/aws/service_connectors/aws_service_connector.py +6 -0
- zenml/integrations/azure/__init__.py +6 -2
- zenml/integrations/azure/flavors/azureml_orchestrator_flavor.py +5 -4
- zenml/integrations/azure/orchestrators/azureml_orchestrator.py +1 -1
- zenml/integrations/bentoml/model_deployers/bentoml_model_deployer.py +85 -19
- zenml/integrations/bentoml/services/__init__.py +15 -4
- zenml/integrations/bentoml/services/bentoml_container_deployment.py +399 -0
- zenml/integrations/bentoml/services/{bentoml_deployment.py → bentoml_local_deployment.py} +81 -40
- zenml/{steps/base_parameters.py → integrations/bentoml/services/deployment_type.py} +8 -5
- zenml/integrations/bentoml/steps/bento_builder.py +1 -0
- zenml/integrations/bentoml/steps/bentoml_deployer.py +93 -41
- zenml/integrations/github/code_repositories/github_code_repository.py +1 -1
- zenml/integrations/gitlab/code_repositories/gitlab_code_repository.py +6 -1
- zenml/integrations/huggingface/__init__.py +1 -6
- zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +3 -3
- zenml/integrations/lightning/orchestrators/lightning_orchestrator.py +3 -3
- zenml/integrations/lightning/orchestrators/lightning_orchestrator_entrypoint.py +2 -2
- zenml/integrations/mlflow/experiment_trackers/mlflow_experiment_tracker.py +6 -3
- zenml/integrations/mlflow/model_registries/mlflow_model_registry.py +6 -0
- zenml/integrations/mlflow/services/mlflow_deployment.py +2 -2
- zenml/integrations/mlflow/steps/mlflow_deployer.py +1 -1
- zenml/integrations/mlflow/steps/mlflow_registry.py +1 -1
- zenml/integrations/neptune/experiment_trackers/run_state.py +2 -2
- zenml/integrations/pytorch/materializers/base_pytorch_materializer.py +8 -2
- zenml/integrations/pytorch/materializers/pytorch_module_materializer.py +4 -1
- zenml/integrations/s3/artifact_stores/s3_artifact_store.py +98 -0
- zenml/integrations/s3/flavors/s3_artifact_store_flavor.py +14 -0
- zenml/integrations/s3/utils.py +40 -0
- zenml/integrations/tensorflow/__init__.py +0 -9
- zenml/logging/step_logging.py +13 -15
- zenml/{new/pipelines → login}/__init__.py +4 -1
- zenml/login/credentials.py +346 -0
- zenml/login/credentials_store.py +603 -0
- zenml/{new → login/pro}/__init__.py +4 -1
- zenml/login/pro/client.py +496 -0
- zenml/login/pro/constants.py +34 -0
- zenml/{lineage_graph/edge.py → login/pro/models.py} +9 -8
- zenml/{zen_server/deploy/terraform/providers → login/pro/organization}/__init__.py +2 -2
- zenml/login/pro/organization/client.py +79 -0
- zenml/{lineage_graph/node/base_node.py → login/pro/organization/models.py} +13 -12
- zenml/{new/steps → login/pro/tenant}/__init__.py +2 -1
- zenml/login/pro/tenant/client.py +92 -0
- zenml/login/pro/tenant/models.py +174 -0
- zenml/login/pro/utils.py +121 -0
- zenml/{cli → login}/web_login.py +64 -28
- zenml/materializers/__init__.py +2 -0
- zenml/materializers/base_materializer.py +43 -9
- zenml/materializers/built_in_materializer.py +1 -1
- zenml/materializers/uuid_materializer.py +79 -0
- zenml/metadata/lazy_load.py +10 -7
- zenml/metadata/metadata_types.py +49 -0
- zenml/model/lazy_load.py +85 -4
- zenml/model/model.py +61 -83
- zenml/model/utils.py +47 -118
- zenml/models/__init__.py +6 -0
- zenml/models/v2/base/base.py +12 -8
- zenml/models/v2/base/filter.py +9 -0
- zenml/models/v2/core/artifact_version.py +53 -25
- zenml/models/v2/core/component.py +54 -19
- zenml/models/v2/core/flavor.py +13 -13
- zenml/models/v2/core/model.py +4 -1
- zenml/models/v2/core/model_version.py +4 -6
- zenml/models/v2/core/model_version_artifact.py +3 -1
- zenml/models/v2/core/model_version_pipeline_run.py +3 -1
- zenml/models/v2/core/pipeline.py +3 -1
- zenml/models/v2/core/pipeline_run.py +24 -3
- zenml/models/v2/core/run_metadata.py +2 -2
- zenml/models/v2/core/run_template.py +3 -1
- zenml/models/v2/core/stack.py +7 -3
- zenml/models/v2/core/step_run.py +58 -14
- zenml/models/v2/misc/auth_models.py +11 -2
- zenml/models/v2/misc/server_models.py +2 -4
- zenml/orchestrators/base_orchestrator.py +41 -4
- zenml/orchestrators/input_utils.py +52 -36
- zenml/orchestrators/step_launcher.py +50 -171
- zenml/orchestrators/step_run_utils.py +574 -0
- zenml/orchestrators/step_runner.py +83 -120
- zenml/orchestrators/utils.py +46 -180
- zenml/pipelines/__init__.py +3 -16
- zenml/{new/pipelines → pipelines}/pipeline_context.py +3 -18
- zenml/pipelines/pipeline_decorator.py +34 -60
- zenml/{new/pipelines/pipeline.py → pipelines/pipeline_definition.py} +210 -207
- zenml/{new/pipelines → pipelines}/run_utils.py +11 -10
- zenml/services/local/local_daemon_entrypoint.py +4 -4
- zenml/services/service.py +2 -2
- zenml/stack/stack.py +3 -108
- zenml/stack/stack_component.py +2 -78
- zenml/stack/utils.py +26 -14
- zenml/stack_deployments/aws_stack_deployment.py +3 -0
- zenml/step_operators/step_operator_entrypoint_configuration.py +1 -1
- zenml/steps/__init__.py +3 -9
- zenml/steps/base_step.py +25 -267
- zenml/steps/entrypoint_function_utils.py +2 -80
- zenml/{new/steps → steps}/step_context.py +12 -66
- zenml/steps/step_decorator.py +42 -89
- zenml/steps/step_invocation.py +16 -60
- zenml/steps/utils.py +4 -23
- zenml/utils/dashboard_utils.py +16 -51
- zenml/utils/materializer_utils.py +1 -1
- zenml/utils/requirements_utils.py +71 -0
- zenml/utils/singleton.py +15 -3
- zenml/utils/source_utils.py +39 -2
- zenml/utils/typing_utils.py +8 -28
- zenml/utils/visualization_utils.py +1 -1
- zenml/zen_server/auth.py +44 -39
- zenml/zen_server/dashboard/assets/{404-Y50hSt65.js → 404-DT4QRUqN.js} +1 -1
- zenml/zen_server/dashboard/assets/@radix-DP6vWzyx.js +85 -0
- zenml/zen_server/dashboard/assets/@react-router-BMhZulnd.js +29 -0
- zenml/zen_server/dashboard/assets/@reactflow-8U9qNlMR.js +17 -0
- zenml/zen_server/dashboard/assets/@tanstack-BUCbhJyH.js +22 -0
- zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-xLR9a1iw.js → AlertDialogDropdownItem-C6N2rGrB.js} +1 -1
- zenml/zen_server/dashboard/assets/{CodeSnippet-IxXNxUDa.js → CodeSnippet-CqybNv0k.js} +1 -1
- zenml/zen_server/dashboard/assets/{CollapsibleCard-BhutZbBL.js → CollapsibleCard-0r_8G2Lj.js} +1 -1
- zenml/zen_server/dashboard/assets/{Commands-Bf-rd1z8.js → Commands-BDjgBQKi.js} +1 -1
- zenml/zen_server/dashboard/assets/ComponentBadge-DUiEYJHu.js +1 -0
- zenml/zen_server/dashboard/assets/ComponentFallbackDialog-BFoH5K4V.js +1 -0
- zenml/zen_server/dashboard/assets/ComponentIcon-CAIoUis2.js +1 -0
- zenml/zen_server/dashboard/assets/{CopyButton-DcFHidFJ.js → CopyButton-C745BrKi.js} +1 -1
- zenml/zen_server/dashboard/assets/{CsvVizualization-QSbjrfxw.js → CsvVizualization-PpAq0CeZ.js} +5 -5
- zenml/zen_server/dashboard/assets/{DialogItem-Cd3HqST4.js → DialogItem-DcVCZEew.js} +1 -1
- zenml/zen_server/dashboard/assets/{DisplayDate-DkCy54Bp.js → DisplayDate-BeXgUG_C.js} +1 -1
- zenml/zen_server/dashboard/assets/{EmptyState-Cs3DEmso.js → EmptyState-DeK7H4pr.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-BhwdmqK7.js → Error-BMlzibXj.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-0pBpTwTm.js → Helpbox-BLf40fLV.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-BTK_EUKT.js → Infobox-BwisKifi.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-CA3DFMcM.js → InlineAvatar-jEgodSgX.js} +1 -1
- zenml/zen_server/dashboard/assets/{Lock-CmIn0szs.js → Lock-3lLt1ih0.js} +1 -1
- zenml/zen_server/dashboard/assets/MarkdownVisualization-8O9kTr-2.js +14 -0
- zenml/zen_server/dashboard/assets/{NumberBox-CrN0_kqI.js → NumberBox-T9eELfLZ.js} +1 -1
- zenml/zen_server/dashboard/assets/{Partials-QLOZw624.js → Partials-YPBB3V4q.js} +1 -1
- zenml/zen_server/dashboard/assets/{PasswordChecker-DE71J_3F.js → PasswordChecker-CW0kqY0W.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderIcon-C16CCIN4.js → ProviderIcon-Bb3Xha5A.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderRadio-D3FuCHf3.js → ProviderRadio-BROY1700.js} +1 -1
- zenml/zen_server/dashboard/assets/RunSelector-DCiL3M1c.js +1 -0
- zenml/zen_server/dashboard/assets/SearchField-DfUiGFVd.js +1 -0
- zenml/zen_server/dashboard/assets/{SecretTooltip-BaMwHF-Q.js → SecretTooltip-C_qByGWB.js} +1 -1
- zenml/zen_server/dashboard/assets/{SetPassword-DuIC65H9.js → SetPassword-7pRB00El.js} +1 -1
- zenml/zen_server/dashboard/assets/{Tick-DJTCF0Re.js → Tick-CykQFPj2.js} +1 -1
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-CUm-DMpw.js → UpdatePasswordSchemas-DckMEkFf.js} +1 -1
- zenml/zen_server/dashboard/assets/{UsageReason-CKw0juLF.js → UsageReason-DVceN14P.js} +1 -1
- zenml/zen_server/dashboard/assets/{WizardFooter-Cv9ApYWU.js → WizardFooter-CW0Cvd70.js} +1 -1
- zenml/zen_server/dashboard/assets/{check-circle-DOoS4yhF.js → check-circle-Dwxliy1Z.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-down-Cwb-W_B_.js → chevron-down-8wLBS5pQ.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-right-double-c9H46Kl8.js → chevron-right-double-DoD8iXWM.js} +1 -1
- zenml/zen_server/dashboard/assets/{cloud-only-BB4BVa6E.js → cloud-only-B-s_HMDm.js} +1 -1
- zenml/zen_server/dashboard/assets/{code-browser-BJYErIjr.js → code-browser-CZUQs3Wa.js} +1 -1
- zenml/zen_server/dashboard/assets/{copy-CaGlDsUy.js → copy-CaSMXwiU.js} +1 -1
- zenml/zen_server/dashboard/assets/{create-stack-F29xAUEx.js → create-stack-CEmaPZ4c.js} +1 -1
- zenml/zen_server/dashboard/assets/delete-run-D-LKbGyz.js +1 -0
- zenml/zen_server/dashboard/assets/{docker-BFAFXr2_.js → docker-BFNgg-z3.js} +1 -1
- zenml/zen_server/dashboard/assets/{dots-horizontal-C6K59vUm.js → dots-horizontal-DK5Duzx4.js} +1 -1
- zenml/zen_server/dashboard/assets/{form-schemas-BKXwSDK2.js → form-schemas-1AyOCx90.js} +1 -1
- zenml/zen_server/dashboard/assets/{gcp-Dj6ntk0L.js → gcp-7M2Yf3ZK.js} +1 -1
- zenml/zen_server/dashboard/assets/{help-CwN931fX.js → help-Dam461dC.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-5GJ5ysEZ.js → index-BVJ8n2-j.js} +1 -1
- zenml/zen_server/dashboard/assets/index-Bpmj40BI.js +1 -0
- zenml/zen_server/dashboard/assets/index-CbU4Ln_E.css +1 -0
- zenml/zen_server/dashboard/assets/{index-D-mtoBj3.js → index-DKPhqP2B.js} +1 -1
- zenml/zen_server/dashboard/assets/index-QQb7wQEC.js +55 -0
- zenml/zen_server/dashboard/assets/index.esm-cuVep_NJ.js +1 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-400-normal-BLGc9T1a.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-400-normal-ZzOtrSSW.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-500-normal-D4Vwzodn.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-500-normal-DH2hs3aW.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-600-normal-BGBWG807.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-600-normal-BuzJQFbW.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-400-normal-BPnxn4xp.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-400-normal-Dc4VJyIJ.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-500-normal-BShVwWPj.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-500-normal-CUiC4oBV.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-600-normal-Bt9VVOA-.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-600-normal-CaqZN2hq.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-400-normal-BZzXV7-1.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-400-normal-DxZsaF_h.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-500-normal-CeQXL5ds.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-500-normal-d_eO-yCQ.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-600-normal-CwicyhtI.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-600-normal-Dhlb-90d.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-400-normal-Bput3-QP.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-400-normal-DCpCPQOf.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-500-normal-B6guLgqG.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-500-normal-M2hEX8vc.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-600-normal-C9WLioJ8.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-600-normal-Cnui8OiR.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-400-normal-BOOGhInR.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-400-normal-gitzw0hO.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-500-normal-D2bGa7uu.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-500-normal-deR1Tlfd.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-600-normal-B5cFAncS.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-600-normal-D273HNI0.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-400-normal-C1t-h-pH.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-400-normal-hnt3BR84.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-500-normal-CIS2RHJS.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-500-normal-UMdmhHu2.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-600-normal-BnYJhD27.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-600-normal-CAF0vJDd.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-400-normal-BUNmGMP1.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-500-normal-DQPw2Hwd.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-600-normal-Cm6aH8_k.woff +0 -0
- zenml/zen_server/dashboard/assets/{kubernetes-BjbR6D-1.js → kubernetes--g7r02Zu.js} +1 -1
- zenml/zen_server/dashboard/assets/{layout-Dru15_XR.js → layout-DCSYN7-C.js} +1 -1
- zenml/zen_server/dashboard/assets/{link-external-BT2L8hAQ.js → link-external-CBEk6kEG.js} +1 -1
- zenml/zen_server/dashboard/assets/{login-mutation-ax6iL2Mb.js → login-mutation-DTcAFP1l.js} +1 -1
- zenml/zen_server/dashboard/assets/{logs-GiDJXbLS.js → logs-D5bdJGur.js} +1 -1
- zenml/zen_server/dashboard/assets/not-found-Cc-JkRH2.js +1 -0
- zenml/zen_server/dashboard/assets/{package-DYKZ5jKW.js → package-Cs35Szwh.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-HkVBdZl6.js → page-9yplj5JT.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-uORspyRu.js → page-B-y2XKIc.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BBpOxVcY.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BDg1F-Ug.js → page-BQQKaabe.js} +2 -2
- zenml/zen_server/dashboard/assets/page-BRInM1Lg.js +1 -0
- zenml/zen_server/dashboard/assets/{page-CvKnNK1S.js → page-BjjlMk7s.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BukXK1Aa.js → page-Bvd7YH2A.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DcTjHmYZ.js → page-C0N5q3l7.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CT3Nep8W.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DuqYMYmH.js → page-C_f47pBf.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DRfcRK1w.js → page-ClUVkl-O.js} +1 -1
- zenml/zen_server/dashboard/assets/page-Cmv8C_yM.js +3 -0
- zenml/zen_server/dashboard/assets/{page-p0BhSAWx.js → page-CyN2bdWG.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CzzXH4fs.js +1 -0
- zenml/zen_server/dashboard/assets/{page-6mfzecin.js → page-DH_Z7iW1.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-8kYmrh0B.js → page-DIOXwhiD.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BXarY9K2.js → page-DLixvR-7.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DTlGjgnG.js +1 -0
- zenml/zen_server/dashboard/assets/page-Dbpl86h0.js +1 -0
- zenml/zen_server/dashboard/assets/{page-MAXyfXBq.js → page-Ddgy6kDS.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DtCAfBLy.js +9 -0
- zenml/zen_server/dashboard/assets/{page-CKHNAq7z.js → page-Dx16z7nA.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DMSLXKGT.js → page-DzpVUZ8f.js} +1 -1
- zenml/zen_server/dashboard/assets/page-McUyYbo1.js +1 -0
- zenml/zen_server/dashboard/assets/{page-miU2rhYG.js → page-N4qoPHKb.js} +1 -1
- zenml/zen_server/dashboard/assets/page-T1P3RyAR.js +1 -0
- zenml/zen_server/dashboard/assets/{page-3qPX9WYH.js → page-bKaULTGG.js} +1 -1
- zenml/zen_server/dashboard/assets/page-sbXUJy9t.js +1 -0
- zenml/zen_server/dashboard/assets/{persist-CfJMar_k.js → persist-CP0JmYZ4.js} +1 -1
- zenml/zen_server/dashboard/assets/{persist-BxIR2XZs.js → persist-DNb5cdrU.js} +1 -1
- zenml/zen_server/dashboard/assets/{plus-Bc8eLSDM.js → plus-C9IxgN2M.js} +1 -1
- zenml/zen_server/dashboard/assets/{refresh-hfgWPeto.js → refresh-BVu22P_C.js} +1 -1
- zenml/zen_server/dashboard/assets/{rocket-SESCGQXm.js → rocket-CONEmRmB.js} +1 -1
- zenml/zen_server/dashboard/assets/{sharedSchema-vub0rii3.js → sharedSchema-TMLu-nYQ.js} +1 -1
- zenml/zen_server/dashboard/assets/stack-detail-query-xmYxSsUY.js +1 -0
- zenml/zen_server/dashboard/assets/{tick-circle-m-hJG8i9.js → tick-circle-CM1ZScbQ.js} +1 -1
- zenml/zen_server/dashboard/assets/{trash-DUWZWzse.js → trash-DkJHMOg7.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-FGVP7X2U.js → update-server-settings-mutation-DsU8cNVl.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-CbAPzsmT.js → url-D5le3J4q.js} +1 -1
- zenml/zen_server/dashboard/assets/zod-D89GC_vc.js +1 -0
- zenml/zen_server/dashboard/index.html +7 -7
- zenml/zen_server/deploy/__init__.py +7 -16
- zenml/zen_server/deploy/base_provider.py +46 -73
- zenml/zen_server/deploy/{local → daemon}/__init__.py +3 -3
- zenml/zen_server/deploy/{local/local_provider.py → daemon/daemon_provider.py} +44 -63
- zenml/zen_server/deploy/{local/local_zen_server.py → daemon/daemon_zen_server.py} +50 -28
- zenml/zen_server/deploy/deployer.py +90 -171
- zenml/zen_server/deploy/deployment.py +20 -12
- zenml/zen_server/deploy/docker/docker_provider.py +9 -28
- zenml/zen_server/deploy/docker/docker_zen_server.py +19 -9
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/exceptions.py +11 -0
- zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +1 -1
- zenml/zen_server/jwt.py +9 -9
- zenml/zen_server/routers/artifact_version_endpoints.py +1 -1
- zenml/zen_server/routers/auth_endpoints.py +30 -8
- zenml/zen_server/routers/runs_endpoints.py +0 -28
- zenml/zen_server/routers/stack_components_endpoints.py +1 -1
- zenml/zen_server/routers/workspaces_endpoints.py +1 -1
- zenml/zen_server/template_execution/runner_entrypoint_configuration.py +7 -4
- zenml/zen_server/template_execution/utils.py +8 -63
- zenml/zen_server/utils.py +67 -69
- zenml/zen_server/zen_server_api.py +107 -17
- zenml/zen_stores/base_zen_store.py +4 -51
- zenml/zen_stores/migrations/versions/0.67.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0.68.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0.68.1_release.py +23 -0
- zenml/zen_stores/migrations/versions/1d8f30c54477_migrate_to_new_.py +124 -0
- zenml/zen_stores/migrations/versions/c22561cbb3a9_add_artifact_unique_constraints.py +86 -0
- zenml/zen_stores/rest_zen_store.py +325 -147
- zenml/zen_stores/schemas/api_key_schemas.py +9 -4
- zenml/zen_stores/schemas/artifact_schemas.py +21 -2
- zenml/zen_stores/schemas/artifact_visualization_schemas.py +1 -1
- zenml/zen_stores/schemas/component_schemas.py +49 -6
- zenml/zen_stores/schemas/device_schemas.py +9 -4
- zenml/zen_stores/schemas/flavor_schemas.py +1 -1
- zenml/zen_stores/schemas/model_schemas.py +1 -1
- zenml/zen_stores/schemas/pipeline_run_schemas.py +12 -4
- zenml/zen_stores/schemas/service_schemas.py +1 -1
- zenml/zen_stores/schemas/step_run_schemas.py +3 -3
- zenml/zen_stores/schemas/trigger_schemas.py +1 -1
- zenml/zen_stores/sql_zen_store.py +422 -145
- zenml/zen_stores/template_utils.py +3 -1
- {zenml_nightly-0.66.0.dev20240927.dist-info → zenml_nightly-0.68.1.dev20241102.dist-info}/METADATA +20 -18
- {zenml_nightly-0.66.0.dev20240927.dist-info → zenml_nightly-0.68.1.dev20241102.dist-info}/RECORD +344 -506
- {zenml_nightly-0.66.0.dev20240927.dist-info → zenml_nightly-0.68.1.dev20241102.dist-info}/WHEEL +1 -1
- zenml/api.py +0 -60
- zenml/cli/stack_recipes.py +0 -469
- zenml/lineage_graph/__init__.py +0 -34
- zenml/lineage_graph/lineage_graph.py +0 -244
- zenml/lineage_graph/node/__init__.py +0 -32
- zenml/lineage_graph/node/artifact_node.py +0 -51
- zenml/lineage_graph/node/step_node.py +0 -41
- zenml/model/model_version.py +0 -38
- zenml/new/pipelines/code_archive.py +0 -157
- zenml/new/pipelines/pipeline_decorator.py +0 -118
- zenml/new/steps/step_decorator.py +0 -176
- zenml/pipelines/base_pipeline.py +0 -273
- zenml/post_execution/__init__.py +0 -30
- zenml/post_execution/pipeline.py +0 -55
- zenml/post_execution/pipeline_run.py +0 -55
- zenml/services/terraform/__init__.py +0 -14
- zenml/services/terraform/terraform_service.py +0 -441
- zenml/steps/external_artifact.py +0 -26
- zenml/steps/step_environment.py +0 -108
- zenml/steps/step_output.py +0 -36
- zenml/utils/mlstacks_utils.py +0 -635
- zenml/utils/terraform_utils.py +0 -43
- zenml/zen_server/dashboard/assets/@radix-DnFH_oo1.js +0 -85
- zenml/zen_server/dashboard/assets/@react-router-APVeuk-U.js +0 -29
- zenml/zen_server/dashboard/assets/@reactflow-ytavUpwh.js +0 -17
- zenml/zen_server/dashboard/assets/@tanstack-QbMbTrh5.js +0 -22
- zenml/zen_server/dashboard/assets/ComponentBadge-gKR1OIwG.js +0 -1
- zenml/zen_server/dashboard/assets/ExecutionStatus-D6r6aK8J.js +0 -1
- zenml/zen_server/dashboard/assets/MarkdownVisualization-DS05sfBm.js +0 -14
- zenml/zen_server/dashboard/assets/SearchField-BzmfxS0L.js +0 -1
- zenml/zen_server/dashboard/assets/all-pipeline-runs-query-BA3R2Sey.js +0 -1
- zenml/zen_server/dashboard/assets/delete-run-CP0pcJ3U.js +0 -1
- zenml/zen_server/dashboard/assets/index-BhJ6ZJxv.css +0 -1
- zenml/zen_server/dashboard/assets/index-Ci0nJ8EZ.js +0 -55
- zenml/zen_server/dashboard/assets/index.esm-BE1uqCX5.js +0 -1
- zenml/zen_server/dashboard/assets/inter-cyrillic-400-normal-Df6ckaLK.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-400-normal-JrS_4yms.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-500-normal-BRrLR67x.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-500-normal-DskEQOpE.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-600-normal-DDpWG8g5.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-600-normal-iz1--dBq.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-400-normal-CzG7Kr3z.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-400-normal-tyfMZHQw.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-500-normal-DOnSzjnx.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-500-normal-Xebo2OyJ.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-600-normal-DpA2xaRd.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-cyrillic-ext-600-normal-KAwcVx6H.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-400-normal-DQXyrmoy.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-400-normal-DvIPHDQ7.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-500-normal-BjpBGs91.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-500-normal-CmOavsDc.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-600-normal-B-l8Lzzd.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-600-normal-BLZsI-P3.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-400-normal-CIdlr5YK.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-400-normal-_Rr29XE2.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-500-normal-2pdUafRD.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-500-normal-Dtavx3qw.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-600-normal-BmtRFZgT.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-greek-ext-600-normal-CkBLDEl_.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-400-normal-BT1H-PT_.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-400-normal-Cdi8t5Mu.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-500-normal-D4I8BKCx.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-500-normal-kWhwEdDH.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-600-normal-B2Ssfs8e.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-600-normal-Dbvh0wvx.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-400-normal-8tIzm-yw.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-400-normal-D3W-OpO-.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-500-normal-B9u8Q_zH.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-500-normal-SuUkSNTU.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-600-normal-Dg0Bk0Yr.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-latin-ext-600-normal-ao35dkSb.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-400-normal-Cnt0N5Vm.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-400-normal-DIOGfGLL.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-500-normal-0i6yoQMg.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-500-normal-5IkPJ6Nk.woff2 +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-600-normal-BQ_dbMbg.woff +0 -0
- zenml/zen_server/dashboard/assets/inter-vietnamese-600-normal-DjnxGF-L.woff2 +0 -0
- zenml/zen_server/dashboard/assets/not-found-DbjllLY_.js +0 -1
- zenml/zen_server/dashboard/assets/page-B1n7_W7z.js +0 -1
- zenml/zen_server/dashboard/assets/page-BZZhLo2u.js +0 -1
- zenml/zen_server/dashboard/assets/page-Bbf_oBjn.js +0 -1
- zenml/zen_server/dashboard/assets/page-BjjuBvZG.js +0 -9
- zenml/zen_server/dashboard/assets/page-CHaQkFK5.js +0 -1
- zenml/zen_server/dashboard/assets/page-CS0SYFK8.js +0 -1
- zenml/zen_server/dashboard/assets/page-DGM1CbYT.js +0 -2
- zenml/zen_server/dashboard/assets/page-DOmIZ2ra.js +0 -1
- zenml/zen_server/dashboard/assets/page-DYVmJ9_w.js +0 -3
- zenml/zen_server/dashboard/assets/page-Dwow2doB.js +0 -1
- zenml/zen_server/dashboard/assets/stack-detail-query-DQcyzG-2.js +0 -1
- zenml/zen_server/dashboard/assets/zod-uFd1wBcd.js +0 -1
- zenml/zen_server/dashboard_legacy/_redirects +0 -1
- zenml/zen_server/dashboard_legacy/asset-manifest.json +0 -131
- zenml/zen_server/dashboard_legacy/favicon.ico +0 -0
- zenml/zen_server/dashboard_legacy/index.html +0 -1
- zenml/zen_server/dashboard_legacy/manifest.json +0 -25
- zenml/zen_server/dashboard_legacy/precache-manifest.6d320abb70db612019dda6c4948e7a90.js +0 -462
- zenml/zen_server/dashboard_legacy/robots.txt +0 -2
- zenml/zen_server/dashboard_legacy/service-worker.js +0 -39
- zenml/zen_server/dashboard_legacy/static/css/2.5b37d44a.chunk.css +0 -16
- zenml/zen_server/dashboard_legacy/static/css/2.5b37d44a.chunk.css.map +0 -1
- zenml/zen_server/dashboard_legacy/static/css/main.e79dff04.chunk.css +0 -2
- zenml/zen_server/dashboard_legacy/static/css/main.e79dff04.chunk.css.map +0 -1
- zenml/zen_server/dashboard_legacy/static/js/2.7934458d.chunk.js +0 -3
- zenml/zen_server/dashboard_legacy/static/js/2.7934458d.chunk.js.LICENSE.txt +0 -95
- zenml/zen_server/dashboard_legacy/static/js/2.7934458d.chunk.js.map +0 -1
- zenml/zen_server/dashboard_legacy/static/js/main.fa9299d5.chunk.js +0 -2
- zenml/zen_server/dashboard_legacy/static/js/main.fa9299d5.chunk.js.map +0 -1
- zenml/zen_server/dashboard_legacy/static/js/runtime-main.bfca2edd.js +0 -2
- zenml/zen_server/dashboard_legacy/static/js/runtime-main.bfca2edd.js.map +0 -1
- zenml/zen_server/dashboard_legacy/static/media/AlertTriangle.28aee535.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/ArrowSquareOut.abfb9bc7.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/Back.86c23a22.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/BookOpen.5cb101ff.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/BoundingBox.1eb98717.svg +0 -10
- zenml/zen_server/dashboard_legacy/static/media/Burger.9b1c67d7.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Cached.2381fb8d.svg +0 -1
- zenml/zen_server/dashboard_legacy/static/media/Calendar.356e11c7.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/ChartBarHorizontal.0247447b.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/ChartLine.0d79e18d.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/ChatDots.2e1c9211.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/Check.dad6beb2.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/CheckCircleFilled.c19566d0.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Checkbox.af50e31e.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/ChevronDown.f860ce32.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/ChevronDownLight.6642d756.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/ChevronLeft.f6edfcdb.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/CircleCheck.f98fd6ca.svg +0 -1
- zenml/zen_server/dashboard_legacy/static/media/Clock.ffc9de95.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Close.74e9efbc.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/CloseWithBorder.6960930a.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/CloseWithoutBorder.cd6f71df.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/CloudArrowUp.0aecb235.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/Code.ef0f33b5.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Config.0be63f8a.svg +0 -1
- zenml/zen_server/dashboard_legacy/static/media/Connector.9fd46ef1.svg +0 -10
- zenml/zen_server/dashboard_legacy/static/media/Copy.36e2112a.svg +0 -1
- zenml/zen_server/dashboard_legacy/static/media/Dashboard.d05787e0.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Data.b1c3b5f8.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Delete.3c361b28.svg +0 -8
- zenml/zen_server/dashboard_legacy/static/media/Docs.7541d478.svg +0 -7
- zenml/zen_server/dashboard_legacy/static/media/Download.fba04d87.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/Edit.490eb294.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/EmptyRightArrow.23749d01.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Example.6396cd37.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/Extension.1394cd4a.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Eye.d9e4ee62.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/Failed.0213c1a0.svg +0 -1
- zenml/zen_server/dashboard_legacy/static/media/FileText.1f15bacd.svg +0 -7
- zenml/zen_server/dashboard_legacy/static/media/Filter.ab6b9c0d.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Folders.12b29887.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/FunnelFill.6df4c143.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/GitCommit.7dd9c2aa.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/GitHub_Logo.cefc2023.png +0 -0
- zenml/zen_server/dashboard_legacy/static/media/Graph.2c63a892.svg +0 -11
- zenml/zen_server/dashboard_legacy/static/media/History.08329240.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Home.0843b0d5.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/ImageBuilder.ea762d9c.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/InProgress.304a0edc.svg +0 -1
- zenml/zen_server/dashboard_legacy/static/media/Info.9fe10c5c.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/KeyboardReturn.491afbe3.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Link.72bbb55d.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/Lock.30f5e1fe.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/Lock2.a769ea52.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/LockKey.92f21621.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/Logs.8bf4d005.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/MinusCircle.4188f418.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/ModelRegistry.f0de050a.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/MultiUser.a2ba7c67.svg +0 -10
- zenml/zen_server/dashboard_legacy/static/media/PaginationFirst.92628634.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/PaginationLast.00d3c732.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/PaginationNext.86158845.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/PaginationPrev.60c18a88.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Pen.f2d831d4.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/PhotoCamera.179d6d4c.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Pipeline.30d298b0.svg +0 -7
- zenml/zen_server/dashboard_legacy/static/media/Plus.5aa1c16b.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/PlusCircle.92d860dd.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/Repositories.71a36b8c.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/RightArrow.f30d3871.svg +0 -29
- zenml/zen_server/dashboard_legacy/static/media/Rocket.63bf7b9d.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/RocketLaunch.1bff2b59.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/Rubik-Medium.c87313aa.ttf +0 -0
- zenml/zen_server/dashboard_legacy/static/media/Rubik-Regular.b3d0902b.ttf +0 -0
- zenml/zen_server/dashboard_legacy/static/media/Run.daec4fb2.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/Search.d1afcce5.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/Settings.59ca73ae.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/Share2.46c3ff66.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/SignOut.6aa718c5.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/SimplePlus.5cf7ec20.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/SingleUser.bef3a095.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/SourceCodePro-Regular.b484b32f.ttf +0 -0
- zenml/zen_server/dashboard_legacy/static/media/Stack.19b604ac.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/StackComponent.b1ba90b5.svg +0 -4
- zenml/zen_server/dashboard_legacy/static/media/Star.f0c25022.svg +0 -9
- zenml/zen_server/dashboard_legacy/static/media/StarOutline.94ca8cd9.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Storefront.4b4796fe.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/Stream.543e3039.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/SupportAgent.510ddf1f.svg +0 -8
- zenml/zen_server/dashboard_legacy/static/media/Table.77033750.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/Tool.d5785486.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/UserPlus.741a99d7.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/Verified.0625b2a0.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/addNew.4fb6c939.svg +0 -8
- zenml/zen_server/dashboard_legacy/static/media/arrowClose.cbd53f3f.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/arrowOpen.6ceef0af.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/check_small.30bc0138.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/circleArrowSideClose.98d6013e.svg +0 -18
- zenml/zen_server/dashboard_legacy/static/media/circleArrowSideOpen.63653df6.svg +0 -18
- zenml/zen_server/dashboard_legacy/static/media/image.104fd14b.png +0 -0
- zenml/zen_server/dashboard_legacy/static/media/imageAddIcon.e83004a9.svg +0 -7
- zenml/zen_server/dashboard_legacy/static/media/logo.93333e5c.svg +0 -1
- zenml/zen_server/dashboard_legacy/static/media/logo_small.4204397d.svg +0 -3
- zenml/zen_server/dashboard_legacy/static/media/logo_white.d4b4414e.svg +0 -20
- zenml/zen_server/dashboard_legacy/static/media/notConnected.5e2c8ea7.svg +0 -8
- zenml/zen_server/dashboard_legacy/static/media/plugin-fallback.72c294e6.svg +0 -6
- zenml/zen_server/dashboard_legacy/static/media/share.bcd998b0.svg +0 -5
- zenml/zen_server/dashboard_legacy/static/media/stars.08a9b19a.svg +0 -8
- zenml/zen_server/deploy/terraform/__init__.py +0 -41
- zenml/zen_server/deploy/terraform/providers/aws_provider.py +0 -61
- zenml/zen_server/deploy/terraform/providers/azure_provider.py +0 -59
- zenml/zen_server/deploy/terraform/providers/gcp_provider.py +0 -59
- zenml/zen_server/deploy/terraform/providers/terraform_provider.py +0 -331
- zenml/zen_server/deploy/terraform/recipes/aws/.gitignore +0 -8
- zenml/zen_server/deploy/terraform/recipes/aws/helm.tf +0 -20
- zenml/zen_server/deploy/terraform/recipes/aws/ingress.tf +0 -30
- zenml/zen_server/deploy/terraform/recipes/aws/outputs.tf +0 -7
- zenml/zen_server/deploy/terraform/recipes/aws/printf.cmd +0 -2
- zenml/zen_server/deploy/terraform/recipes/aws/sql.tf +0 -62
- zenml/zen_server/deploy/terraform/recipes/aws/terraform.tf +0 -44
- zenml/zen_server/deploy/terraform/recipes/aws/variables.tf +0 -167
- zenml/zen_server/deploy/terraform/recipes/aws/vpc.tf +0 -47
- zenml/zen_server/deploy/terraform/recipes/aws/zen_server.tf +0 -103
- zenml/zen_server/deploy/terraform/recipes/azure/.gitignore +0 -8
- zenml/zen_server/deploy/terraform/recipes/azure/helm.tf +0 -20
- zenml/zen_server/deploy/terraform/recipes/azure/ingress.tf +0 -30
- zenml/zen_server/deploy/terraform/recipes/azure/key_vault.tf +0 -73
- zenml/zen_server/deploy/terraform/recipes/azure/outputs.tf +0 -7
- zenml/zen_server/deploy/terraform/recipes/azure/printf.cmd +0 -2
- zenml/zen_server/deploy/terraform/recipes/azure/rg.tf +0 -36
- zenml/zen_server/deploy/terraform/recipes/azure/sql.tf +0 -65
- zenml/zen_server/deploy/terraform/recipes/azure/terraform.tf +0 -52
- zenml/zen_server/deploy/terraform/recipes/azure/variables.tf +0 -176
- zenml/zen_server/deploy/terraform/recipes/azure/zen_server.tf +0 -103
- zenml/zen_server/deploy/terraform/recipes/gcp/.gitignore +0 -8
- zenml/zen_server/deploy/terraform/recipes/gcp/helm.tf +0 -20
- zenml/zen_server/deploy/terraform/recipes/gcp/ingress.tf +0 -30
- zenml/zen_server/deploy/terraform/recipes/gcp/outputs.tf +0 -7
- zenml/zen_server/deploy/terraform/recipes/gcp/printf.cmd +0 -2
- zenml/zen_server/deploy/terraform/recipes/gcp/sql.tf +0 -64
- zenml/zen_server/deploy/terraform/recipes/gcp/terraform.tf +0 -44
- zenml/zen_server/deploy/terraform/recipes/gcp/variables.tf +0 -171
- zenml/zen_server/deploy/terraform/recipes/gcp/zen_server.tf +0 -114
- zenml/zen_server/deploy/terraform/terraform_zen_server.py +0 -246
- /zenml/{new/pipelines → pipelines}/build_utils.py +0 -0
- /zenml/{new/steps → steps}/decorated_step.py +0 -0
- {zenml_nightly-0.66.0.dev20240927.dist-info → zenml_nightly-0.68.1.dev20241102.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.66.0.dev20240927.dist-info → zenml_nightly-0.68.1.dev20241102.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,603 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2024. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""ZenML login credentials store support."""
|
15
|
+
|
16
|
+
import os
|
17
|
+
from datetime import datetime, timedelta, timezone
|
18
|
+
from typing import Dict, List, Optional, Tuple, Union, cast
|
19
|
+
|
20
|
+
from zenml.config.global_config import GlobalConfiguration
|
21
|
+
from zenml.constants import (
|
22
|
+
ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING,
|
23
|
+
handle_bool_env_var,
|
24
|
+
)
|
25
|
+
from zenml.io import fileio
|
26
|
+
from zenml.logger import get_logger
|
27
|
+
from zenml.login.credentials import APIToken, ServerCredentials, ServerType
|
28
|
+
from zenml.login.pro.constants import ZENML_PRO_API_URL
|
29
|
+
from zenml.login.pro.tenant.models import TenantRead
|
30
|
+
from zenml.models import OAuthTokenResponse, ServerModel
|
31
|
+
from zenml.utils import yaml_utils
|
32
|
+
from zenml.utils.singleton import SingletonMetaClass
|
33
|
+
|
34
|
+
logger = get_logger(__name__)
|
35
|
+
|
36
|
+
CREDENTIALS_STORE_FILENAME = "credentials.yaml"
|
37
|
+
|
38
|
+
# How long to keep tokens in the credentials store after their expiration date before evicting them
|
39
|
+
TOKEN_STORE_EVICTION_TIME = 60 * 60 * 24 * 7 # 1 week
|
40
|
+
|
41
|
+
|
42
|
+
class CredentialsStore(metaclass=SingletonMetaClass):
|
43
|
+
"""Login credentials store.
|
44
|
+
|
45
|
+
This is a singleton object that maintains a cache of all API tokens and API
|
46
|
+
keys that are configured for the ZenML servers that the client connects to
|
47
|
+
throughout its lifetime.
|
48
|
+
|
49
|
+
The cache is persistent and it is backed by a `credentials.yaml` YAML file
|
50
|
+
kept in the global configuration location. The Credentials Store cache is
|
51
|
+
populated mainly in the following ways:
|
52
|
+
|
53
|
+
1. when the user runs `zenml login` to authenticate to a ZenML Pro
|
54
|
+
server, the ZenML Pro API token fetched from the web login flow is
|
55
|
+
stored in the Credentials Store.
|
56
|
+
2. when the user runs `zenml login` to authenticate to a regular ZenML
|
57
|
+
server with the web login flow, the ZenML server API token fetched
|
58
|
+
through the web login flow is stored in the Credentials Store
|
59
|
+
3. when the user runs `zenml login` to authenticate to any ZenML server
|
60
|
+
using an API key, the API key is stored in the Credentials Store
|
61
|
+
4. when the REST zen store is initialized, it starts up not yet
|
62
|
+
authenticated. Then, if/when it needs to authenticate or re-authenticate
|
63
|
+
to the remote server, it will use whatever form of credentials it finds
|
64
|
+
in the Credentials Store, in order of priority:
|
65
|
+
|
66
|
+
* if it finds an API token that is not expired (e.g. authorized
|
67
|
+
device API tokens fetched through the web login flow or short-lived
|
68
|
+
session API tokens fetched through some other means of
|
69
|
+
authentication), it will use that to authenticate
|
70
|
+
* for ZenML servers that use an API key to authenticate, it will use
|
71
|
+
that to fetch a short-lived ZenML Pro server API token that it also
|
72
|
+
stores in the Credentials Store
|
73
|
+
* for ZenML Pro servers, it exchanges the longer-lived ZenML Pro API
|
74
|
+
token into a short lived ZenML Pro server API token
|
75
|
+
|
76
|
+
Alongside credentials, the Credentials Store is also used to store
|
77
|
+
additional server information:
|
78
|
+
* ZenML Pro tenant information populated by the `zenml login` command
|
79
|
+
* ZenML server information populated by the REST zen store by fetching
|
80
|
+
the server's information endpoint after authenticating
|
81
|
+
|
82
|
+
"""
|
83
|
+
|
84
|
+
credentials: Dict[str, ServerCredentials]
|
85
|
+
last_modified_time: Optional[float] = None
|
86
|
+
|
87
|
+
def __init__(self) -> None:
|
88
|
+
"""Initializes the login credentials store with values loaded from the credentials YAML file.
|
89
|
+
|
90
|
+
CredentialsStore is a singleton class: only one instance can exist.
|
91
|
+
Calling this constructor multiple times will always yield the same
|
92
|
+
instance.
|
93
|
+
"""
|
94
|
+
self.credentials = {}
|
95
|
+
self._load_credentials()
|
96
|
+
|
97
|
+
@classmethod
|
98
|
+
def reset_instance(
|
99
|
+
cls, store: Optional["CredentialsStore"] = None
|
100
|
+
) -> None:
|
101
|
+
"""Reset the singleton instance of the CredentialsStore.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
store: Optional instance of the CredentialsStore to set as the
|
105
|
+
singleton instance. If None, a new instance will be created.
|
106
|
+
"""
|
107
|
+
current_store = cls.get_instance()
|
108
|
+
if current_store is not None and current_store is not store:
|
109
|
+
# Delete the credentials file from disk if it exists, otherwise
|
110
|
+
# the credentials will be reloaded from the file when the new
|
111
|
+
# instance is created and this call will have no effect
|
112
|
+
current_store._delete_credentials_file()
|
113
|
+
|
114
|
+
cls._clear(store) # type: ignore[arg-type]
|
115
|
+
if store:
|
116
|
+
store._save_credentials()
|
117
|
+
|
118
|
+
@classmethod
|
119
|
+
def get_instance(cls) -> Optional["CredentialsStore"]:
|
120
|
+
"""Get the singleton instance of the CredentialsStore.
|
121
|
+
|
122
|
+
Returns:
|
123
|
+
The singleton instance of the CredentialsStore.
|
124
|
+
"""
|
125
|
+
return cast(CredentialsStore, cls._instance())
|
126
|
+
|
127
|
+
@property
|
128
|
+
def _credentials_file(self) -> str:
|
129
|
+
"""Path to the file where the credentials are stored.
|
130
|
+
|
131
|
+
Returns:
|
132
|
+
The path to the file where the credentials are stored.
|
133
|
+
"""
|
134
|
+
config_path = GlobalConfiguration().config_directory
|
135
|
+
return os.path.join(config_path, CREDENTIALS_STORE_FILENAME)
|
136
|
+
|
137
|
+
def _load_credentials(self) -> None:
|
138
|
+
"""Load the credentials from the YAML file if it exists."""
|
139
|
+
if handle_bool_env_var(ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING):
|
140
|
+
return
|
141
|
+
|
142
|
+
credentials_file = self._credentials_file
|
143
|
+
credentials_store = {}
|
144
|
+
|
145
|
+
if fileio.exists(credentials_file):
|
146
|
+
try:
|
147
|
+
credentials_store = yaml_utils.read_yaml(credentials_file)
|
148
|
+
except Exception as e:
|
149
|
+
logger.error(
|
150
|
+
f"Failed to load credentials file {credentials_file}: {e}. "
|
151
|
+
)
|
152
|
+
self.last_modified_time = os.path.getmtime(credentials_file)
|
153
|
+
|
154
|
+
if credentials_store is None:
|
155
|
+
# This can happen for example if the config file is empty
|
156
|
+
credentials_store = {}
|
157
|
+
elif not isinstance(credentials_store, dict):
|
158
|
+
logger.warning(
|
159
|
+
f"The credentials file {credentials_file} is corrupted. "
|
160
|
+
"Creating a new credentials file."
|
161
|
+
)
|
162
|
+
credentials_store = {}
|
163
|
+
|
164
|
+
self.credentials = {}
|
165
|
+
for server_url, token_data in credentials_store.items():
|
166
|
+
try:
|
167
|
+
self.credentials[server_url] = ServerCredentials(**token_data)
|
168
|
+
except ValueError as e:
|
169
|
+
logger.warning(
|
170
|
+
f"Failed to load credentials for {server_url}: {e}. "
|
171
|
+
"Ignoring this token."
|
172
|
+
)
|
173
|
+
|
174
|
+
def _save_credentials(self) -> None:
|
175
|
+
"""Dump the current credentials store to the YAML file."""
|
176
|
+
if handle_bool_env_var(ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING):
|
177
|
+
return
|
178
|
+
credentials_file = self._credentials_file
|
179
|
+
credentials_store = {
|
180
|
+
server_url: credential.model_dump(
|
181
|
+
mode="json", exclude_none=True, exclude_unset=True
|
182
|
+
)
|
183
|
+
for server_url, credential in self.credentials.items()
|
184
|
+
# Evict tokens that have expired past the eviction time
|
185
|
+
# and have no API key or username/password to fall back on
|
186
|
+
if credential.api_key
|
187
|
+
or credential.username
|
188
|
+
and credential.password is not None
|
189
|
+
or credential.api_token
|
190
|
+
and (
|
191
|
+
not credential.api_token.expires_at
|
192
|
+
or credential.api_token.expires_at
|
193
|
+
+ timedelta(seconds=TOKEN_STORE_EVICTION_TIME)
|
194
|
+
> datetime.now(timezone.utc)
|
195
|
+
)
|
196
|
+
}
|
197
|
+
yaml_utils.write_yaml(credentials_file, credentials_store)
|
198
|
+
self.last_modified_time = os.path.getmtime(credentials_file)
|
199
|
+
|
200
|
+
def _delete_credentials_file(self) -> None:
|
201
|
+
"""Delete the credentials file."""
|
202
|
+
if handle_bool_env_var(ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING):
|
203
|
+
return
|
204
|
+
credentials_file = self._credentials_file
|
205
|
+
if fileio.exists(credentials_file):
|
206
|
+
fileio.remove(credentials_file)
|
207
|
+
self.last_modified_time = None
|
208
|
+
|
209
|
+
def check_and_reload_from_file(self) -> None:
|
210
|
+
"""Check if the credentials file has been modified and reload it if necessary."""
|
211
|
+
if handle_bool_env_var(ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING):
|
212
|
+
return
|
213
|
+
if not self.last_modified_time:
|
214
|
+
return
|
215
|
+
credentials_file = self._credentials_file
|
216
|
+
try:
|
217
|
+
last_modified_time = os.path.getmtime(credentials_file)
|
218
|
+
except FileNotFoundError:
|
219
|
+
# The credentials file has been deleted
|
220
|
+
self.last_modified_time = None
|
221
|
+
return
|
222
|
+
if last_modified_time != self.last_modified_time:
|
223
|
+
self._load_credentials()
|
224
|
+
|
225
|
+
def get_password(
|
226
|
+
self, server_url: str
|
227
|
+
) -> Tuple[Optional[str], Optional[str]]:
|
228
|
+
"""Retrieve the username and password from the credentials store for a specific server URL.
|
229
|
+
|
230
|
+
Args:
|
231
|
+
server_url: The server URL for which to retrieve the username and
|
232
|
+
password.
|
233
|
+
|
234
|
+
Returns:
|
235
|
+
The stored username and password if they exist, None otherwise.
|
236
|
+
"""
|
237
|
+
self.check_and_reload_from_file()
|
238
|
+
credential = self.credentials.get(server_url)
|
239
|
+
if credential:
|
240
|
+
return credential.username, credential.password
|
241
|
+
return None, None
|
242
|
+
|
243
|
+
def get_api_key(self, server_url: str) -> Optional[str]:
|
244
|
+
"""Retrieve an API key from the credentials store for a specific server URL.
|
245
|
+
|
246
|
+
Args:
|
247
|
+
server_url: The server URL for which to retrieve the API key.
|
248
|
+
|
249
|
+
Returns:
|
250
|
+
The stored API key if it exists, None otherwise.
|
251
|
+
"""
|
252
|
+
self.check_and_reload_from_file()
|
253
|
+
credential = self.credentials.get(server_url)
|
254
|
+
if credential:
|
255
|
+
return credential.api_key
|
256
|
+
return None
|
257
|
+
|
258
|
+
def get_token(
|
259
|
+
self, server_url: str, allow_expired: bool = False
|
260
|
+
) -> Optional[APIToken]:
|
261
|
+
"""Retrieve a valid token from the credentials store for a specific server URL.
|
262
|
+
|
263
|
+
Args:
|
264
|
+
server_url: The server URL for which to retrieve the token.
|
265
|
+
allow_expired: Whether to allow expired tokens to be returned. The
|
266
|
+
default behavior is to return None if a token does exist but is
|
267
|
+
expired.
|
268
|
+
|
269
|
+
Returns:
|
270
|
+
The stored token if it exists and is not expired, None otherwise.
|
271
|
+
"""
|
272
|
+
self.check_and_reload_from_file()
|
273
|
+
credential = self.credentials.get(server_url)
|
274
|
+
if credential:
|
275
|
+
token = credential.api_token
|
276
|
+
if token and (not token.expired or allow_expired):
|
277
|
+
return token
|
278
|
+
return None
|
279
|
+
|
280
|
+
def get_credentials(self, server_url: str) -> Optional[ServerCredentials]:
|
281
|
+
"""Retrieve the credentials for a specific server URL.
|
282
|
+
|
283
|
+
Args:
|
284
|
+
server_url: The server URL for which to retrieve the credentials.
|
285
|
+
|
286
|
+
Returns:
|
287
|
+
The stored credentials if they exist, None otherwise.
|
288
|
+
"""
|
289
|
+
self.check_and_reload_from_file()
|
290
|
+
return self.credentials.get(server_url)
|
291
|
+
|
292
|
+
def get_pro_token(self, allow_expired: bool = False) -> Optional[APIToken]:
|
293
|
+
"""Retrieve a valid token from the credentials store for the ZenML Pro API server.
|
294
|
+
|
295
|
+
Args:
|
296
|
+
allow_expired: Whether to allow expired tokens to be returned. The
|
297
|
+
default behavior is to return None if a token does exist but is
|
298
|
+
expired.
|
299
|
+
|
300
|
+
Returns:
|
301
|
+
The stored token if it exists and is not expired, None otherwise.
|
302
|
+
"""
|
303
|
+
return self.get_token(ZENML_PRO_API_URL, allow_expired)
|
304
|
+
|
305
|
+
def get_pro_credentials(
|
306
|
+
self, allow_expired: bool = False
|
307
|
+
) -> Optional[ServerCredentials]:
|
308
|
+
"""Retrieve a valid token from the credentials store for the ZenML Pro API server.
|
309
|
+
|
310
|
+
Args:
|
311
|
+
allow_expired: Whether to allow expired tokens to be returned. The
|
312
|
+
default behavior is to return None if a token does exist but is
|
313
|
+
expired.
|
314
|
+
|
315
|
+
Returns:
|
316
|
+
The stored credentials if they exist and are not expired, None otherwise.
|
317
|
+
"""
|
318
|
+
credential = self.get_credentials(ZENML_PRO_API_URL)
|
319
|
+
if (
|
320
|
+
credential
|
321
|
+
and credential.api_token
|
322
|
+
and (not credential.api_token.expired or allow_expired)
|
323
|
+
):
|
324
|
+
return credential
|
325
|
+
return None
|
326
|
+
|
327
|
+
def clear_pro_credentials(self) -> None:
|
328
|
+
"""Delete the token from the store for the ZenML Pro API server."""
|
329
|
+
self.clear_token(ZENML_PRO_API_URL)
|
330
|
+
|
331
|
+
def clear_all_pro_tokens(self) -> None:
|
332
|
+
"""Delete all tokens from the store for ZenML Pro API servers."""
|
333
|
+
for server_url, server in self.credentials.copy().items():
|
334
|
+
if server.type == ServerType.PRO:
|
335
|
+
if server.api_key:
|
336
|
+
continue
|
337
|
+
self.clear_token(server_url)
|
338
|
+
|
339
|
+
def has_valid_authentication(self, url: str) -> bool:
|
340
|
+
"""Check if a valid authentication credential for the given server URL is stored.
|
341
|
+
|
342
|
+
Args:
|
343
|
+
url: The server URL for which to check the authentication.
|
344
|
+
|
345
|
+
Returns:
|
346
|
+
bool: True if a valid token or API key is stored, False otherwise.
|
347
|
+
"""
|
348
|
+
self.check_and_reload_from_file()
|
349
|
+
credential = self.credentials.get(url)
|
350
|
+
|
351
|
+
if not credential:
|
352
|
+
return False
|
353
|
+
if credential.api_key or (
|
354
|
+
credential.username and credential.password is not None
|
355
|
+
):
|
356
|
+
return True
|
357
|
+
token = credential.api_token
|
358
|
+
return token is not None and not token.expired
|
359
|
+
|
360
|
+
def has_valid_pro_authentication(self) -> bool:
|
361
|
+
"""Check if a valid token for the ZenML Pro API server is stored.
|
362
|
+
|
363
|
+
Returns:
|
364
|
+
bool: True if a valid token is stored, False otherwise.
|
365
|
+
"""
|
366
|
+
return self.get_token(ZENML_PRO_API_URL) is not None
|
367
|
+
|
368
|
+
def set_api_key(
|
369
|
+
self,
|
370
|
+
server_url: str,
|
371
|
+
api_key: str,
|
372
|
+
) -> None:
|
373
|
+
"""Store an API key in the credentials store for a specific server URL.
|
374
|
+
|
375
|
+
If an API token or a password is already stored for the server URL, they
|
376
|
+
will be replaced by the API key.
|
377
|
+
|
378
|
+
Args:
|
379
|
+
server_url: The server URL for which the token is to be stored.
|
380
|
+
api_key: The API key to store.
|
381
|
+
"""
|
382
|
+
self.check_and_reload_from_file()
|
383
|
+
credential = self.credentials.get(server_url)
|
384
|
+
if credential and credential.api_key != api_key:
|
385
|
+
# Reset the API token if a new or updated API key is set, because
|
386
|
+
# the current token might have been issued for a different account
|
387
|
+
credential.api_token = None
|
388
|
+
credential.api_key = api_key
|
389
|
+
credential.username = None
|
390
|
+
credential.password = None
|
391
|
+
else:
|
392
|
+
self.credentials[server_url] = ServerCredentials(
|
393
|
+
url=server_url, api_key=api_key
|
394
|
+
)
|
395
|
+
|
396
|
+
self._save_credentials()
|
397
|
+
|
398
|
+
def set_password(
|
399
|
+
self,
|
400
|
+
server_url: str,
|
401
|
+
username: str,
|
402
|
+
password: str,
|
403
|
+
) -> None:
|
404
|
+
"""Store a username and password in the credentials store for a specific server URL.
|
405
|
+
|
406
|
+
If an API token is already stored for the server URL, it will be
|
407
|
+
replaced by the username and password.
|
408
|
+
|
409
|
+
Args:
|
410
|
+
server_url: The server URL for which the token is to be stored.
|
411
|
+
username: The username to store.
|
412
|
+
password: The password to store.
|
413
|
+
"""
|
414
|
+
self.check_and_reload_from_file()
|
415
|
+
credential = self.credentials.get(server_url)
|
416
|
+
if credential and (
|
417
|
+
credential.username != username or credential.password != password
|
418
|
+
):
|
419
|
+
# Reset the API token if a new or updated password is set, because
|
420
|
+
# the current token might have been issued for a different account
|
421
|
+
credential.api_token = None
|
422
|
+
credential.username = username
|
423
|
+
credential.password = password
|
424
|
+
credential.api_key = None
|
425
|
+
else:
|
426
|
+
self.credentials[server_url] = ServerCredentials(
|
427
|
+
url=server_url, username=username, password=password
|
428
|
+
)
|
429
|
+
|
430
|
+
self._save_credentials()
|
431
|
+
|
432
|
+
def set_token(
|
433
|
+
self,
|
434
|
+
server_url: str,
|
435
|
+
token_response: OAuthTokenResponse,
|
436
|
+
) -> APIToken:
|
437
|
+
"""Store an API token received from an OAuth2 server.
|
438
|
+
|
439
|
+
Args:
|
440
|
+
server_url: The server URL for which the token is to be stored.
|
441
|
+
token_response: Token response received from an OAuth2 server.
|
442
|
+
|
443
|
+
Returns:
|
444
|
+
APIToken: The stored token.
|
445
|
+
"""
|
446
|
+
self.check_and_reload_from_file()
|
447
|
+
if token_response.expires_in:
|
448
|
+
expires_at = datetime.now(timezone.utc) + timedelta(
|
449
|
+
seconds=token_response.expires_in
|
450
|
+
)
|
451
|
+
# Best practice to calculate the leeway depending on the token
|
452
|
+
# expiration time:
|
453
|
+
#
|
454
|
+
# - for short-lived tokens (less than 1 hour), use a fixed leeway of
|
455
|
+
# a few seconds (e.g., 30 seconds)
|
456
|
+
# - for longer-lived tokens (e.g., 1 hour or more), use a
|
457
|
+
# percentage-based leeway of 5-10%
|
458
|
+
if token_response.expires_in < 3600:
|
459
|
+
leeway = 30
|
460
|
+
else:
|
461
|
+
leeway = token_response.expires_in // 20
|
462
|
+
else:
|
463
|
+
expires_at = None
|
464
|
+
leeway = None
|
465
|
+
|
466
|
+
api_token = APIToken(
|
467
|
+
access_token=token_response.access_token,
|
468
|
+
expires_in=token_response.expires_in,
|
469
|
+
expires_at=expires_at,
|
470
|
+
leeway=leeway,
|
471
|
+
cookie_name=token_response.cookie_name,
|
472
|
+
device_id=token_response.device_id,
|
473
|
+
device_metadata=token_response.device_metadata,
|
474
|
+
)
|
475
|
+
|
476
|
+
credential = self.credentials.get(server_url)
|
477
|
+
if credential:
|
478
|
+
credential.api_token = api_token
|
479
|
+
else:
|
480
|
+
self.credentials[server_url] = ServerCredentials(
|
481
|
+
url=server_url, api_token=api_token
|
482
|
+
)
|
483
|
+
|
484
|
+
self._save_credentials()
|
485
|
+
|
486
|
+
return api_token
|
487
|
+
|
488
|
+
def set_bare_token(
|
489
|
+
self,
|
490
|
+
server_url: str,
|
491
|
+
token: str,
|
492
|
+
) -> APIToken:
|
493
|
+
"""Store a bare API token.
|
494
|
+
|
495
|
+
Args:
|
496
|
+
server_url: The server URL for which the token is to be stored.
|
497
|
+
token: The token to store.
|
498
|
+
|
499
|
+
Returns:
|
500
|
+
APIToken: The stored token.
|
501
|
+
"""
|
502
|
+
self.check_and_reload_from_file()
|
503
|
+
|
504
|
+
api_token = APIToken(
|
505
|
+
access_token=token,
|
506
|
+
)
|
507
|
+
|
508
|
+
credential = self.credentials.get(server_url)
|
509
|
+
if credential:
|
510
|
+
credential.api_token = api_token
|
511
|
+
else:
|
512
|
+
self.credentials[server_url] = ServerCredentials(
|
513
|
+
url=server_url, api_token=api_token
|
514
|
+
)
|
515
|
+
|
516
|
+
self._save_credentials()
|
517
|
+
|
518
|
+
return api_token
|
519
|
+
|
520
|
+
def update_server_info(
|
521
|
+
self,
|
522
|
+
server_url: str,
|
523
|
+
server_info: Union[ServerModel, TenantRead],
|
524
|
+
) -> None:
|
525
|
+
"""Update the server information stored for a specific server URL.
|
526
|
+
|
527
|
+
Args:
|
528
|
+
server_url: The server URL for which the server information is to be
|
529
|
+
updated.
|
530
|
+
server_info: Updated server information.
|
531
|
+
"""
|
532
|
+
self.check_and_reload_from_file()
|
533
|
+
|
534
|
+
credential = self.credentials.get(server_url)
|
535
|
+
if not credential:
|
536
|
+
# No credentials stored for this server URL, nothing to update
|
537
|
+
return
|
538
|
+
|
539
|
+
credential.update_server_info(server_info)
|
540
|
+
self._save_credentials()
|
541
|
+
|
542
|
+
def clear_token(self, server_url: str) -> None:
|
543
|
+
"""Delete a token from the store for a specific server URL.
|
544
|
+
|
545
|
+
Args:
|
546
|
+
server_url: The server URL for which to delete the token.
|
547
|
+
"""
|
548
|
+
self.check_and_reload_from_file()
|
549
|
+
|
550
|
+
if server_url in self.credentials:
|
551
|
+
credential = self.credentials[server_url]
|
552
|
+
if (
|
553
|
+
not credential.api_key
|
554
|
+
and not credential.username
|
555
|
+
and not credential.password is not None
|
556
|
+
):
|
557
|
+
# Only delete the credential entry if there is no API key or
|
558
|
+
# username/password to fall back on
|
559
|
+
del self.credentials[server_url]
|
560
|
+
else:
|
561
|
+
credential.api_token = None
|
562
|
+
self._save_credentials()
|
563
|
+
|
564
|
+
def clear_credentials(self, server_url: str) -> None:
|
565
|
+
"""Delete all credentials from the store for a specific server URL.
|
566
|
+
|
567
|
+
Args:
|
568
|
+
server_url: The server URL for which to delete the credentials.
|
569
|
+
"""
|
570
|
+
self.check_and_reload_from_file()
|
571
|
+
|
572
|
+
if server_url in self.credentials:
|
573
|
+
del self.credentials[server_url]
|
574
|
+
self._save_credentials()
|
575
|
+
|
576
|
+
def list_credentials(
|
577
|
+
self, type: Optional[ServerType] = None
|
578
|
+
) -> List[ServerCredentials]:
|
579
|
+
"""Get all credentials stored in the credentials store.
|
580
|
+
|
581
|
+
Args:
|
582
|
+
type: Optional server type to filter the credentials by.
|
583
|
+
|
584
|
+
Returns:
|
585
|
+
A list of all credentials stored in the credentials store.
|
586
|
+
"""
|
587
|
+
self.check_and_reload_from_file()
|
588
|
+
|
589
|
+
credentials = list(self.credentials.values())
|
590
|
+
|
591
|
+
if type is not None:
|
592
|
+
credentials = [c for c in credentials if c and c.type == type]
|
593
|
+
|
594
|
+
return credentials
|
595
|
+
|
596
|
+
|
597
|
+
def get_credentials_store() -> CredentialsStore:
|
598
|
+
"""Get the global credentials store instance.
|
599
|
+
|
600
|
+
Returns:
|
601
|
+
The global credentials store instance.
|
602
|
+
"""
|
603
|
+
return CredentialsStore()
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) ZenML GmbH
|
1
|
+
# Copyright (c) ZenML GmbH 2024. All Rights Reserved.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -11,3 +11,6 @@
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
12
|
# or implied. See the License for the specific language governing
|
13
13
|
# permissions and limitations under the License.
|
14
|
+
"""ZenML Pro client."""
|
15
|
+
|
16
|
+
|