zenml-nightly 0.61.0.dev20240712__py3-none-any.whl → 0.62.0.dev20240726__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 +2 -2
- RELEASE_NOTES.md +40 -0
- zenml/VERSION +1 -1
- zenml/__init__.py +2 -0
- zenml/cli/stack.py +114 -248
- zenml/cli/stack_components.py +5 -3
- zenml/constants.py +3 -0
- zenml/enums.py +16 -0
- zenml/integrations/__init__.py +1 -0
- zenml/integrations/azure/__init__.py +2 -2
- zenml/integrations/constants.py +1 -0
- zenml/integrations/databricks/__init__.py +52 -0
- zenml/integrations/databricks/flavors/__init__.py +30 -0
- zenml/integrations/databricks/flavors/databricks_model_deployer_flavor.py +118 -0
- zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +147 -0
- zenml/integrations/databricks/model_deployers/__init__.py +20 -0
- zenml/integrations/databricks/model_deployers/databricks_model_deployer.py +249 -0
- zenml/integrations/databricks/orchestrators/__init__.py +20 -0
- zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +497 -0
- zenml/integrations/databricks/orchestrators/databricks_orchestrator_entrypoint_config.py +97 -0
- zenml/integrations/databricks/services/__init__.py +19 -0
- zenml/integrations/databricks/services/databricks_deployment.py +407 -0
- zenml/integrations/databricks/utils/__init__.py +14 -0
- zenml/integrations/databricks/utils/databricks_utils.py +87 -0
- zenml/integrations/great_expectations/data_validators/ge_data_validator.py +12 -8
- zenml/integrations/huggingface/materializers/huggingface_datasets_materializer.py +88 -3
- zenml/integrations/huggingface/steps/accelerate_runner.py +1 -7
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +1 -13
- zenml/integrations/kubernetes/orchestrators/manifest_utils.py +22 -4
- zenml/integrations/kubernetes/pod_settings.py +4 -0
- zenml/integrations/lightgbm/__init__.py +1 -0
- zenml/integrations/mlflow/__init__.py +1 -1
- zenml/integrations/mlflow/model_registries/mlflow_model_registry.py +6 -2
- zenml/integrations/mlflow/services/mlflow_deployment.py +1 -1
- zenml/integrations/skypilot_azure/__init__.py +1 -3
- zenml/integrations/skypilot_lambda/__init__.py +1 -1
- zenml/logging/step_logging.py +34 -35
- zenml/materializers/built_in_materializer.py +1 -1
- zenml/materializers/cloudpickle_materializer.py +1 -1
- zenml/model/model.py +1 -1
- zenml/models/v2/core/component.py +29 -0
- zenml/models/v2/core/server_settings.py +0 -20
- zenml/models/v2/misc/full_stack.py +32 -0
- zenml/models/v2/misc/stack_deployment.py +5 -0
- zenml/new/pipelines/run_utils.py +1 -1
- zenml/orchestrators/__init__.py +4 -0
- zenml/orchestrators/step_launcher.py +1 -0
- zenml/orchestrators/wheeled_orchestrator.py +147 -0
- zenml/service_connectors/service_connector_utils.py +408 -0
- zenml/stack_deployments/azure_stack_deployment.py +179 -0
- zenml/stack_deployments/gcp_stack_deployment.py +13 -4
- zenml/stack_deployments/stack_deployment.py +10 -0
- zenml/stack_deployments/utils.py +4 -0
- zenml/steps/base_step.py +7 -5
- zenml/utils/function_utils.py +1 -1
- zenml/utils/pipeline_docker_image_builder.py +8 -0
- zenml/utils/source_utils.py +4 -1
- zenml/zen_server/dashboard/assets/{404-DpJaNHKF.js → 404-B_YdvmwS.js} +1 -1
- zenml/zen_server/dashboard/assets/{@reactflow-DJfzkHO1.js → @reactflow-l_1hUr1S.js} +1 -1
- zenml/zen_server/dashboard/assets/{AwarenessChannel-BYDLT2xC.js → AwarenessChannel-CFg5iX4Z.js} +1 -1
- zenml/zen_server/dashboard/assets/{CodeSnippet-BkOuRmyq.js → CodeSnippet-Dvkx_82E.js} +1 -1
- zenml/zen_server/dashboard/assets/CollapsibleCard-opiuBHHc.js +1 -0
- zenml/zen_server/dashboard/assets/{Commands-ZvWR1BRs.js → Commands-DoN1xrEq.js} +1 -1
- zenml/zen_server/dashboard/assets/{CopyButton-DVwLkafa.js → CopyButton-Cr7xYEPb.js} +1 -1
- zenml/zen_server/dashboard/assets/{CsvVizualization-C2IiqX4I.js → CsvVizualization-Ck-nZ43m.js} +3 -3
- zenml/zen_server/dashboard/assets/{Error-CqX0VqW_.js → Error-kLtljEOM.js} +1 -1
- zenml/zen_server/dashboard/assets/{ExecutionStatus-BoLUXR9t.js → ExecutionStatus-DguLLgTK.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-LFydyVwh.js → Helpbox-BXUMP21n.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-DnENC0sh.js → Infobox-DSt0O-dm.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-CbJtYr0t.js → InlineAvatar-xsrsIGE-.js} +1 -1
- zenml/zen_server/dashboard/assets/Pagination-C6X-mifw.js +1 -0
- zenml/zen_server/dashboard/assets/{SetPassword-BYBdbQDo.js → SetPassword-BXGTWiwj.js} +1 -1
- zenml/zen_server/dashboard/assets/{SuccessStep-Nx743hll.js → SuccessStep-DZC60t0x.js} +1 -1
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DF9gSzE0.js → UpdatePasswordSchemas-DGvwFWO1.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-right-double-BiEMg7rd.js → chevron-right-double-CZBOf6JM.js} +1 -1
- zenml/zen_server/dashboard/assets/cloud-only-C_yFCAkP.js +1 -0
- zenml/zen_server/dashboard/assets/index-BczVOqUf.js +55 -0
- zenml/zen_server/dashboard/assets/index-EpMIKgrI.css +1 -0
- zenml/zen_server/dashboard/assets/{login-mutation-BUnVASxp.js → login-mutation-CrHrndTI.js} +1 -1
- zenml/zen_server/dashboard/assets/logs-D8k8BVFf.js +1 -0
- zenml/zen_server/dashboard/assets/{not-found-B4VnX8gK.js → not-found-DYa4pC-C.js} +1 -1
- zenml/zen_server/dashboard/assets/{package-CsUhPmou.js → package-B3fWP-Dh.js} +1 -1
- zenml/zen_server/dashboard/assets/page-1h_sD1jz.js +1 -0
- zenml/zen_server/dashboard/assets/{page-Sxn82W-5.js → page-1iL8aMqs.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DMOYZppS.js → page-2grKx_MY.js} +1 -1
- zenml/zen_server/dashboard/assets/page-5NCOHOsy.js +1 -0
- zenml/zen_server/dashboard/assets/{page-JyfeDUfu.js → page-8a4UMKXZ.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Bx6o0ARS.js → page-B6h3iaHJ.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BDns21Iz.js +1 -0
- zenml/zen_server/dashboard/assets/{page-3efNCDeb.js → page-BhgCDInH.js} +2 -2
- zenml/zen_server/dashboard/assets/{page-DKlIdAe5.js → page-Bi-wtWiO.js} +2 -2
- zenml/zen_server/dashboard/assets/{page-7zTHbhhI.js → page-BkeAAYwp.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CRTJ0UuR.js → page-BkuQDIf-.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BnaevhnB.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BEs6jK71.js → page-Bq0YxkLV.js} +1 -1
- zenml/zen_server/dashboard/assets/page-Bs2F4eoD.js +2 -0
- zenml/zen_server/dashboard/assets/{page-CUZIGO-3.js → page-C6-UGEbH.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Xu8JEjSU.js → page-CCNRIt_f.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DvCvroOM.js → page-CHNxpz3n.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BpSqIf4B.js → page-DgorQFqi.js} +1 -1
- zenml/zen_server/dashboard/assets/page-K8ebxVIs.js +1 -0
- zenml/zen_server/dashboard/assets/{page-Cx67M0QT.js → page-MFQyIJd3.js} +1 -1
- zenml/zen_server/dashboard/assets/page-TgCF0P_U.js +1 -0
- zenml/zen_server/dashboard/assets/page-ZnCEe-eK.js +9 -0
- zenml/zen_server/dashboard/assets/{page-Dc_7KMQE.js → page-uA5prJGY.js} +1 -1
- zenml/zen_server/dashboard/assets/persist-D7HJNBWx.js +1 -0
- zenml/zen_server/dashboard/assets/plus-C8WOyCzt.js +1 -0
- zenml/zen_server/dashboard/assets/stack-detail-query-Cficsl6d.js +1 -0
- zenml/zen_server/dashboard/assets/update-server-settings-mutation-7d8xi1tS.js +1 -0
- zenml/zen_server/dashboard/assets/{url-DuQMeqYA.js → url-D7mAQGUM.js} +1 -1
- zenml/zen_server/dashboard/index.html +4 -4
- zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
- zenml/zen_server/dashboard_legacy/index.html +1 -1
- zenml/zen_server/dashboard_legacy/{precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js → precache-manifest.12246c7548e71e2c4438e496360de80c.js} +4 -4
- zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
- zenml/zen_server/dashboard_legacy/static/js/main.3b27024b.chunk.js +2 -0
- zenml/zen_server/dashboard_legacy/static/js/{main.382439a7.chunk.js.map → main.3b27024b.chunk.js.map} +1 -1
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/rbac/utils.py +10 -2
- zenml/zen_server/routers/devices_endpoints.py +4 -1
- zenml/zen_server/routers/server_endpoints.py +29 -2
- zenml/zen_server/routers/service_connectors_endpoints.py +57 -0
- zenml/zen_server/routers/steps_endpoints.py +2 -1
- zenml/zen_stores/migrations/versions/0.62.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/b4fca5241eea_migrate_onboarding_state.py +167 -0
- zenml/zen_stores/rest_zen_store.py +4 -0
- zenml/zen_stores/schemas/component_schemas.py +14 -0
- zenml/zen_stores/schemas/server_settings_schemas.py +23 -11
- zenml/zen_stores/sql_zen_store.py +151 -1
- {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/METADATA +5 -5
- {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/RECORD +135 -115
- zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +0 -1
- zenml/zen_server/dashboard/assets/chevron-down-D_ZlKMqH.js +0 -1
- zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +0 -1
- zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +0 -1
- zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +0 -55
- zenml/zen_server/dashboard/assets/index-inApY3KQ.css +0 -1
- zenml/zen_server/dashboard/assets/page-C43QGHTt.js +0 -9
- zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +0 -1
- zenml/zen_server/dashboard/assets/page-CaopxiU1.js +0 -1
- zenml/zen_server/dashboard/assets/page-D7Z399xy.js +0 -1
- zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +0 -1
- zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +0 -2
- zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +0 -1
- zenml/zen_server/dashboard/assets/page-TKXERe16.js +0 -1
- zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +0 -1
- zenml/zen_server/dashboard/assets/update-server-settings-mutation-CR8e3Sir.js +0 -1
- zenml/zen_server/dashboard_legacy/static/js/main.382439a7.chunk.js +0 -2
- {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/entry_points.txt +0 -0
README.md
CHANGED
@@ -318,7 +318,7 @@ the Apache License Version 2.0.
|
|
318
318
|
·
|
319
319
|
<a href="https://github.com/zenml-io/zenml/issues">Report Bug</a>
|
320
320
|
·
|
321
|
-
<a href="https://zenml.io/
|
321
|
+
<a href="https://zenml.io/pro">Sign up for ZenML Pro</a>
|
322
322
|
·
|
323
323
|
<a href="https://www.zenml.io/blog">Read Blog</a>
|
324
324
|
·
|
@@ -327,7 +327,7 @@ the Apache License Version 2.0.
|
|
327
327
|
<a href="https://github.com/zenml-io/zenml-projects">Projects Showcase</a>
|
328
328
|
<br />
|
329
329
|
<br />
|
330
|
-
🎉 Version 0.
|
330
|
+
🎉 Version 0.62.0 is out. Check out the release notes
|
331
331
|
<a href="https://github.com/zenml-io/zenml/releases">here</a>.
|
332
332
|
<br />
|
333
333
|
🖥️ Download our VS Code Extension <a href="https://marketplace.visualstudio.com/items?itemName=ZenML.zenml-vscode">here</a>.
|
RELEASE_NOTES.md
CHANGED
@@ -1,4 +1,44 @@
|
|
1
1
|
<!-- markdown-link-check-disable -->
|
2
|
+
# 0.62.0
|
3
|
+
|
4
|
+
Building on top of the last release, this release adds a new and easy way to deploy a GCP ZenML stack from the dashboard and the CLI. Give it a try by going to the `Stacks` section in the dashboard or running the `zenml stack deploy` command! For more information on this new feature, please do check out [the video and blog](https://www.zenml.io/blog/easy-mlops-pipelines) from our previous release.
|
5
|
+
|
6
|
+
We also [updated our Hugging Face integration](https://github.com/zenml-io/zenml/pull/2851) to support the automatic display of an embedded `datasets` preview pane in the ZenML Dashboard whenever you return a `Dataset` from a step. This was recently released by the Hugging Face datasets team and it allows you to easily visualize and inspect your data from the comfort of the dashboard.
|
7
|
+
|
8
|
+
## What's Changed
|
9
|
+
|
10
|
+
* Fix release action docker limit by @schustmi in https://github.com/zenml-io/zenml/pull/2837
|
11
|
+
* Upgrade ruff and yamlfix to latest versions before running formatting by @christianversloot in https://github.com/zenml-io/zenml/pull/2577
|
12
|
+
* Fixed edge-case where step run is stored incompletely by @AlexejPenner in https://github.com/zenml-io/zenml/pull/2827
|
13
|
+
* Docs for stack registration + deployment wizards by @htahir1 in https://github.com/zenml-io/zenml/pull/2814
|
14
|
+
* Make upgrade checks in formatting script optional by @avishniakov in https://github.com/zenml-io/zenml/pull/2839
|
15
|
+
* Enable migration testing for version 0.61.0 by @schustmi in https://github.com/zenml-io/zenml/pull/2836
|
16
|
+
* One-click GCP stack deployments by @stefannica in https://github.com/zenml-io/zenml/pull/2833
|
17
|
+
* Only login to docker for PRs with secret access by @schustmi in https://github.com/zenml-io/zenml/pull/2842
|
18
|
+
* Add GCP Stack creation Wizard (CLI) by @avishniakov in https://github.com/zenml-io/zenml/pull/2826
|
19
|
+
* Update onboarding by @schustmi in https://github.com/zenml-io/zenml/pull/2794
|
20
|
+
* Merged log files in Step Ops steps might be not available on main process, due to merge in the step op by @avishniakov in https://github.com/zenml-io/zenml/pull/2795
|
21
|
+
* Fix some broken links, copy paste commands, and made secrets more visible by @htahir1 in https://github.com/zenml-io/zenml/pull/2848
|
22
|
+
* Update stack deployment docs and other small fixes by @stefannica in https://github.com/zenml-io/zenml/pull/2846
|
23
|
+
* Improved the `StepInterfaceError` message for missing inputs by @AlexejPenner in https://github.com/zenml-io/zenml/pull/2849
|
24
|
+
* add image pull secrets to k8s pod settings by @wjayesh in https://github.com/zenml-io/zenml/pull/2847
|
25
|
+
* Include apt installation of libgomp1 for docker images with lightgbm by @AlexejPenner in https://github.com/zenml-io/zenml/pull/2813
|
26
|
+
* Patch filter mflow by stage by @whoknowsB in https://github.com/zenml-io/zenml/pull/2798
|
27
|
+
* Bump mlflow to version 2.14.2 by @christianversloot in https://github.com/zenml-io/zenml/pull/2825
|
28
|
+
* Fix Accelerate string arguments passing by @avishniakov in https://github.com/zenml-io/zenml/pull/2845
|
29
|
+
* Fix CI by @schustmi in https://github.com/zenml-io/zenml/pull/2850
|
30
|
+
* Added some visualizations for the HF dataset by @htahir1 in https://github.com/zenml-io/zenml/pull/2851
|
31
|
+
* Fix skypilot versioning for the lambda integration by @wjayesh in https://github.com/zenml-io/zenml/pull/2853
|
32
|
+
* Improve custom visualization docs by @htahir1 in https://github.com/zenml-io/zenml/pull/2855
|
33
|
+
* Fix list typo by @htahir1 in https://github.com/zenml-io/zenml/pull/2856
|
34
|
+
* Endpoint to get existing and prospective resources for service connector by @avishniakov in https://github.com/zenml-io/zenml/pull/2854
|
35
|
+
* Databricks integrations by @safoinme in https://github.com/zenml-io/zenml/pull/2823
|
36
|
+
|
37
|
+
## New Contributors
|
38
|
+
* @whoknowsB made their first contribution in https://github.com/zenml-io/zenml/pull/2798
|
39
|
+
|
40
|
+
**Full Changelog**: https://github.com/zenml-io/zenml/compare/0.61.0...0.62.0
|
41
|
+
|
2
42
|
# 0.61.0
|
3
43
|
|
4
44
|
This release comes with a new and easy way to deploy an AWS ZenML stack from the dashboard and the CLI. Give it a try by going to the `Stacks` section in the dashboard or running the `zenml stack deploy` command!
|
zenml/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.62.0.dev20240726
|
zenml/__init__.py
CHANGED
@@ -56,6 +56,7 @@ from zenml.new.pipelines.pipeline_decorator import pipeline
|
|
56
56
|
from zenml.new.steps.step_decorator import step
|
57
57
|
from zenml.new.steps.step_context import get_step_context
|
58
58
|
from zenml.steps.utils import log_step_metadata
|
59
|
+
from zenml.entrypoints import entrypoint
|
59
60
|
|
60
61
|
__all__ = [
|
61
62
|
"ArtifactConfig",
|
@@ -74,4 +75,5 @@ __all__ = [
|
|
74
75
|
"save_artifact",
|
75
76
|
"show",
|
76
77
|
"step",
|
78
|
+
"entrypoint",
|
77
79
|
]
|
zenml/cli/stack.py
CHANGED
@@ -83,9 +83,10 @@ from zenml.models.v2.misc.full_stack import (
|
|
83
83
|
ComponentInfo,
|
84
84
|
FullStackRequest,
|
85
85
|
ServiceConnectorInfo,
|
86
|
+
ServiceConnectorResourcesInfo,
|
86
87
|
)
|
87
|
-
from zenml.
|
88
|
-
|
88
|
+
from zenml.service_connectors.service_connector_utils import (
|
89
|
+
get_resources_options_from_resource_model_for_full_stack,
|
89
90
|
)
|
90
91
|
from zenml.utils.dashboard_utils import get_component_url, get_stack_url
|
91
92
|
from zenml.utils.io_utils import create_dir_recursive_if_not_exists
|
@@ -329,6 +330,13 @@ def register_stack(
|
|
329
330
|
auto_configure=True,
|
330
331
|
verify=False,
|
331
332
|
)
|
333
|
+
except NotImplementedError:
|
334
|
+
cli_utils.warning(
|
335
|
+
f"The {provider.upper()} service connector libraries are not "
|
336
|
+
"installed properly. Please run `zenml integration install "
|
337
|
+
f"{provider}` and try again to enable auto-discovery of the "
|
338
|
+
"connection configuration."
|
339
|
+
)
|
332
340
|
except Exception:
|
333
341
|
pass
|
334
342
|
if service_connector_response:
|
@@ -390,8 +398,21 @@ def register_stack(
|
|
390
398
|
labels["zenml:wizard"] = "true"
|
391
399
|
if provider:
|
392
400
|
labels["zenml:provider"] = provider
|
393
|
-
|
394
|
-
|
401
|
+
resources_info = None
|
402
|
+
# explore the service connector
|
403
|
+
with console.status(
|
404
|
+
"Exploring resources available to the service connector...\n"
|
405
|
+
):
|
406
|
+
resources_info = (
|
407
|
+
get_resources_options_from_resource_model_for_full_stack(
|
408
|
+
connector_details=service_connector
|
409
|
+
)
|
410
|
+
)
|
411
|
+
if resources_info is None:
|
412
|
+
cli_utils.error(
|
413
|
+
f"Failed to fetch service connector resources information for {service_connector}..."
|
414
|
+
)
|
415
|
+
|
395
416
|
# create components
|
396
417
|
needed_components = (
|
397
418
|
(StackComponentType.ARTIFACT_STORE, artifact_store),
|
@@ -408,21 +429,37 @@ def register_stack(
|
|
408
429
|
else:
|
409
430
|
if isinstance(service_connector, UUID):
|
410
431
|
# find existing components under same connector
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
432
|
+
if (
|
433
|
+
component_type
|
434
|
+
in resources_info.components_resources_info
|
435
|
+
):
|
436
|
+
existing_components = [
|
437
|
+
existing_response
|
438
|
+
for res_info in resources_info.components_resources_info[
|
439
|
+
component_type
|
440
|
+
]
|
441
|
+
for existing_response in res_info.connected_through_service_connector
|
442
|
+
]
|
443
|
+
|
444
|
+
# if some existing components are found - prompt user what to do
|
445
|
+
component_selected: Optional[int] = None
|
419
446
|
component_selected = cli_utils.multi_choice_prompt(
|
420
447
|
object_type=component_type.value.replace("_", " "),
|
421
448
|
choices=[
|
422
|
-
[
|
423
|
-
|
449
|
+
[
|
450
|
+
component.flavor,
|
451
|
+
component.name,
|
452
|
+
component.configuration or "",
|
453
|
+
component.connector_resource_id,
|
454
|
+
]
|
455
|
+
for component in existing_components
|
456
|
+
],
|
457
|
+
headers=[
|
458
|
+
"Type",
|
459
|
+
"Name",
|
460
|
+
"Configuration",
|
461
|
+
"Connected as",
|
424
462
|
],
|
425
|
-
headers=["Name"],
|
426
463
|
prompt_text=f"We found these {component_type.value.replace('_', ' ')} "
|
427
464
|
"connected using the current service connector. Do you "
|
428
465
|
"want to create a new one or use existing one?",
|
@@ -433,61 +470,17 @@ def register_stack(
|
|
433
470
|
component_selected = None
|
434
471
|
|
435
472
|
if component_selected is None:
|
436
|
-
if service_connector_resource_model is None:
|
437
|
-
with console.status(
|
438
|
-
"Exploring resources available to the service connector...\n"
|
439
|
-
):
|
440
|
-
if isinstance(service_connector, UUID):
|
441
|
-
service_connector_resource_model = (
|
442
|
-
client.verify_service_connector(
|
443
|
-
service_connector
|
444
|
-
)
|
445
|
-
)
|
446
|
-
existing_service_connector_info = (
|
447
|
-
client.get_service_connector(
|
448
|
-
service_connector
|
449
|
-
)
|
450
|
-
)
|
451
|
-
can_generate_long_tokens = not existing_service_connector_info.configuration.get(
|
452
|
-
"generate_temporary_tokens", True
|
453
|
-
)
|
454
|
-
else:
|
455
|
-
_, service_connector_resource_model = (
|
456
|
-
client.create_service_connector(
|
457
|
-
name=stack_name,
|
458
|
-
connector_type=service_connector.type,
|
459
|
-
auth_method=service_connector.auth_method,
|
460
|
-
configuration=service_connector.configuration,
|
461
|
-
register=False,
|
462
|
-
)
|
463
|
-
)
|
464
|
-
can_generate_long_tokens = True
|
465
|
-
if service_connector_resource_model is None:
|
466
|
-
cli_utils.error(
|
467
|
-
f"Failed to validate service connector {service_connector}..."
|
468
|
-
)
|
469
|
-
if provider is None:
|
470
|
-
if isinstance(
|
471
|
-
service_connector_resource_model.connector_type,
|
472
|
-
str,
|
473
|
-
):
|
474
|
-
provider = (
|
475
|
-
service_connector_resource_model.connector_type
|
476
|
-
)
|
477
|
-
else:
|
478
|
-
provider = service_connector_resource_model.connector_type.connector_type
|
479
|
-
|
480
473
|
component_info = _get_stack_component_info(
|
481
474
|
component_type=component_type.value,
|
482
|
-
cloud_provider=provider
|
483
|
-
|
475
|
+
cloud_provider=provider
|
476
|
+
or resources_info.connector_type,
|
477
|
+
resources_info=resources_info,
|
484
478
|
service_connector_index=0,
|
485
|
-
can_generate_long_tokens=can_generate_long_tokens,
|
486
479
|
)
|
487
480
|
component_name = stack_name
|
488
481
|
created_objects.add(component_type.value)
|
489
482
|
else:
|
490
|
-
selected_component = existing_components
|
483
|
+
selected_component = existing_components[
|
491
484
|
component_selected
|
492
485
|
]
|
493
486
|
component_info = selected_component.id
|
@@ -498,18 +491,6 @@ def register_stack(
|
|
498
491
|
artifact_store = component_name
|
499
492
|
if component_type == StackComponentType.ORCHESTRATOR:
|
500
493
|
orchestrator = component_name
|
501
|
-
if not isinstance(
|
502
|
-
component_info, UUID
|
503
|
-
) and component_info.flavor.startswith("vm"):
|
504
|
-
if isinstance(
|
505
|
-
service_connector, ServiceConnectorInfo
|
506
|
-
) and service_connector.auth_method in {
|
507
|
-
"service-account",
|
508
|
-
"external-account",
|
509
|
-
}:
|
510
|
-
service_connector.configuration[
|
511
|
-
"generate_temporary_tokens"
|
512
|
-
] = False
|
513
494
|
if component_type == StackComponentType.CONTAINER_REGISTRY:
|
514
495
|
container_registry = component_name
|
515
496
|
|
@@ -1752,12 +1733,12 @@ def deploy(
|
|
1752
1733
|
Markdown(
|
1753
1734
|
"## Configuration\n"
|
1754
1735
|
"You will be asked to provide the following configuration "
|
1755
|
-
"values during the deployment process
|
1756
|
-
)
|
1736
|
+
"values during the deployment process:"
|
1737
|
+
),
|
1738
|
+
"\n",
|
1757
1739
|
)
|
1758
1740
|
|
1759
1741
|
console.print(
|
1760
|
-
"\n",
|
1761
1742
|
deployment_config.configuration,
|
1762
1743
|
no_wrap=True,
|
1763
1744
|
overflow="ignore",
|
@@ -2323,7 +2304,7 @@ def _get_service_connector_info(
|
|
2323
2304
|
"""
|
2324
2305
|
from rich.prompt import Prompt
|
2325
2306
|
|
2326
|
-
if cloud_provider not in {"aws", "gcp"}:
|
2307
|
+
if cloud_provider not in {"aws", "gcp", "azure"}:
|
2327
2308
|
raise ValueError(f"Unknown cloud provider {cloud_provider}")
|
2328
2309
|
|
2329
2310
|
client = Client()
|
@@ -2349,7 +2330,7 @@ def _get_service_connector_info(
|
|
2349
2330
|
choices.append([value.name, required])
|
2350
2331
|
|
2351
2332
|
selected_auth_idx = cli_utils.multi_choice_prompt(
|
2352
|
-
object_type=f"authentication methods for {cloud_provider}",
|
2333
|
+
object_type=f"authentication methods for {cloud_provider.upper()}",
|
2353
2334
|
choices=choices,
|
2354
2335
|
headers=headers,
|
2355
2336
|
prompt_text="Please choose one of the authentication option above",
|
@@ -2393,10 +2374,7 @@ def _get_service_connector_info(
|
|
2393
2374
|
def _get_stack_component_info(
|
2394
2375
|
component_type: str,
|
2395
2376
|
cloud_provider: str,
|
2396
|
-
|
2397
|
-
ServiceConnectorTypedResourcesModel
|
2398
|
-
],
|
2399
|
-
can_generate_long_tokens: bool,
|
2377
|
+
resources_info: ServiceConnectorResourcesInfo,
|
2400
2378
|
service_connector_index: Optional[int] = None,
|
2401
2379
|
) -> ComponentInfo:
|
2402
2380
|
"""Get a stack component info with given type and service connector.
|
@@ -2404,8 +2382,7 @@ def _get_stack_component_info(
|
|
2404
2382
|
Args:
|
2405
2383
|
component_type: The type of component to create.
|
2406
2384
|
cloud_provider: The cloud provider to use.
|
2407
|
-
|
2408
|
-
can_generate_long_tokens: Whether connector can generate long-living tokens.
|
2385
|
+
resources_info: The resources info of the service connector.
|
2409
2386
|
service_connector_index: The index of the service connector to use.
|
2410
2387
|
|
2411
2388
|
Returns:
|
@@ -2420,211 +2397,100 @@ def _get_stack_component_info(
|
|
2420
2397
|
if cloud_provider not in {"aws", "azure", "gcp"}:
|
2421
2398
|
raise ValueError(f"Unknown cloud provider {cloud_provider}")
|
2422
2399
|
|
2423
|
-
AWS_DOCS = (
|
2424
|
-
"https://docs.zenml.io/how-to/auth-management/aws-service-connector"
|
2425
|
-
)
|
2426
|
-
GCP_DOCS = (
|
2427
|
-
"https://docs.zenml.io/how-to/auth-management/gcp-service-connector"
|
2428
|
-
)
|
2429
|
-
|
2430
2400
|
flavor = "undefined"
|
2431
2401
|
service_connector_resource_id = None
|
2432
2402
|
config = {}
|
2403
|
+
choices = [
|
2404
|
+
[cri.flavor, resource_id]
|
2405
|
+
for cri in resources_info.components_resources_info[
|
2406
|
+
StackComponentType(component_type)
|
2407
|
+
]
|
2408
|
+
for resource_id in cri.accessible_by_service_connector
|
2409
|
+
]
|
2433
2410
|
if component_type == "artifact_store":
|
2434
|
-
available_storages: List[str] = []
|
2435
|
-
if cloud_provider == "aws":
|
2436
|
-
for each in service_connector_resource_models:
|
2437
|
-
if each.resource_type == "s3-bucket":
|
2438
|
-
available_storages = each.resource_ids or []
|
2439
|
-
flavor = "s3"
|
2440
|
-
if not available_storages:
|
2441
|
-
cli_utils.error(
|
2442
|
-
"We were unable to find any S3 buckets available "
|
2443
|
-
"to configured service connector. Please, verify "
|
2444
|
-
"that needed permission are granted for the "
|
2445
|
-
"service connector.\nDocumentation for the S3 "
|
2446
|
-
"Buckets configuration can be found at "
|
2447
|
-
f"{AWS_DOCS}#s3-bucket"
|
2448
|
-
)
|
2449
|
-
elif cloud_provider == "azure":
|
2450
|
-
flavor = "azure"
|
2451
|
-
elif cloud_provider == "gcp":
|
2452
|
-
flavor = "gcp"
|
2453
|
-
for each in service_connector_resource_models:
|
2454
|
-
if each.resource_type == "gcs-bucket":
|
2455
|
-
available_storages = each.resource_ids or []
|
2456
|
-
if not available_storages:
|
2457
|
-
cli_utils.error(
|
2458
|
-
"We were unable to find any GCS buckets available "
|
2459
|
-
"to configured service connector. Please, verify "
|
2460
|
-
"that needed permission are granted for the "
|
2461
|
-
"service connector.\nDocumentation for the GCS "
|
2462
|
-
"Buckets configuration can be found at "
|
2463
|
-
f"{GCP_DOCS}#gcs-bucket"
|
2464
|
-
)
|
2465
|
-
|
2466
2411
|
selected_storage_idx = cli_utils.multi_choice_prompt(
|
2467
2412
|
object_type=f"{cloud_provider.upper()} storages",
|
2468
|
-
choices=
|
2469
|
-
headers=["Storage"],
|
2413
|
+
choices=choices,
|
2414
|
+
headers=["Artifact Store Type", "Storage"],
|
2470
2415
|
prompt_text="Please choose one of the storages for the new artifact store:",
|
2471
2416
|
)
|
2472
2417
|
if selected_storage_idx is None:
|
2473
2418
|
cli_utils.error("No storage selected.")
|
2474
2419
|
|
2475
|
-
selected_storage =
|
2420
|
+
selected_storage = choices[selected_storage_idx]
|
2476
2421
|
|
2477
|
-
|
2478
|
-
|
2422
|
+
flavor = selected_storage[0]
|
2423
|
+
config = {"path": selected_storage[1]}
|
2424
|
+
service_connector_resource_id = selected_storage[1]
|
2479
2425
|
elif component_type == "orchestrator":
|
2480
2426
|
|
2481
|
-
def
|
2427
|
+
def query_region(
|
2428
|
+
provider: StackDeploymentProvider,
|
2429
|
+
compute_type: str,
|
2430
|
+
is_skypilot: bool = False,
|
2431
|
+
) -> str:
|
2432
|
+
deployment_info = Client().zen_store.get_stack_deployment_info(
|
2433
|
+
provider
|
2434
|
+
)
|
2482
2435
|
region = Prompt.ask(
|
2483
2436
|
f"Select the location for your {compute_type}:",
|
2484
2437
|
choices=sorted(
|
2485
|
-
|
2486
|
-
|
2487
|
-
|
2488
|
-
)
|
2489
|
-
.locations.values()
|
2438
|
+
deployment_info.skypilot_default_regions.values()
|
2439
|
+
if is_skypilot
|
2440
|
+
else deployment_info.locations.values()
|
2490
2441
|
),
|
2491
2442
|
show_choices=True,
|
2492
2443
|
)
|
2493
2444
|
return region
|
2494
2445
|
|
2495
|
-
if cloud_provider == "aws":
|
2496
|
-
available_orchestrators = []
|
2497
|
-
for each in service_connector_resource_models:
|
2498
|
-
types = []
|
2499
|
-
if each.resource_type == "aws-generic":
|
2500
|
-
types = ["Sagemaker"]
|
2501
|
-
if can_generate_long_tokens:
|
2502
|
-
types.append("Skypilot (EC2)")
|
2503
|
-
if each.resource_type == "kubernetes-cluster":
|
2504
|
-
types = ["Kubernetes"]
|
2505
|
-
|
2506
|
-
if each.resource_ids:
|
2507
|
-
for orchestrator in each.resource_ids:
|
2508
|
-
for t in types:
|
2509
|
-
available_orchestrators.append([t, orchestrator])
|
2510
|
-
if not available_orchestrators:
|
2511
|
-
cli_utils.error(
|
2512
|
-
"We were unable to find any orchestrator engines "
|
2513
|
-
"available to the service connector. Please, verify "
|
2514
|
-
"that needed permission are granted for the "
|
2515
|
-
"service connector.\nDocumentation for the Generic "
|
2516
|
-
"AWS resource configuration can be found at "
|
2517
|
-
f"{AWS_DOCS}#generic-aws-resource\n"
|
2518
|
-
"Documentation for the Kubernetes resource "
|
2519
|
-
"configuration can be found at "
|
2520
|
-
f"{AWS_DOCS}#eks-kubernetes-cluster"
|
2521
|
-
)
|
2522
|
-
elif cloud_provider == "gcp":
|
2523
|
-
available_orchestrators = []
|
2524
|
-
for each in service_connector_resource_models:
|
2525
|
-
types = []
|
2526
|
-
if each.resource_type == "gcp-generic":
|
2527
|
-
types = ["Vertex AI"]
|
2528
|
-
if can_generate_long_tokens:
|
2529
|
-
types.append("Skypilot (Compute)")
|
2530
|
-
if each.resource_type == "kubernetes-cluster":
|
2531
|
-
types = ["Kubernetes"]
|
2532
|
-
|
2533
|
-
if each.resource_ids:
|
2534
|
-
for orchestrator in each.resource_ids:
|
2535
|
-
for t in types:
|
2536
|
-
available_orchestrators.append([t, orchestrator])
|
2537
|
-
if not available_orchestrators:
|
2538
|
-
cli_utils.error(
|
2539
|
-
"We were unable to find any orchestrator engines "
|
2540
|
-
"available to the service connector. Please, verify "
|
2541
|
-
"that needed permission are granted for the "
|
2542
|
-
"service connector.\nDocumentation for the Generic "
|
2543
|
-
"GCP resource configuration can be found at "
|
2544
|
-
f"{GCP_DOCS}#generic-gcp-resource\n"
|
2545
|
-
"Documentation for the GKE Kubernetes resource "
|
2546
|
-
"configuration can be found at "
|
2547
|
-
f"{GCP_DOCS}#gke-kubernetes-cluster"
|
2548
|
-
)
|
2549
|
-
elif cloud_provider == "azure":
|
2550
|
-
pass
|
2551
|
-
|
2552
2446
|
selected_orchestrator_idx = cli_utils.multi_choice_prompt(
|
2553
2447
|
object_type=f"orchestrators on {cloud_provider.upper()}",
|
2554
|
-
choices=
|
2555
|
-
headers=["Orchestrator Type", "
|
2448
|
+
choices=choices,
|
2449
|
+
headers=["Orchestrator Type", "Details"],
|
2556
2450
|
prompt_text="Please choose one of the orchestrators for the new orchestrator:",
|
2557
2451
|
)
|
2558
2452
|
if selected_orchestrator_idx is None:
|
2559
2453
|
cli_utils.error("No orchestrator selected.")
|
2560
2454
|
|
2561
|
-
selected_orchestrator =
|
2562
|
-
selected_orchestrator_idx
|
2563
|
-
]
|
2455
|
+
selected_orchestrator = choices[selected_orchestrator_idx]
|
2564
2456
|
|
2565
2457
|
config = {}
|
2566
|
-
|
2567
|
-
|
2458
|
+
flavor = selected_orchestrator[0]
|
2459
|
+
if flavor == "sagemaker":
|
2568
2460
|
execution_role = Prompt.ask("Enter an execution role ARN:")
|
2569
2461
|
config["execution_role"] = execution_role
|
2570
|
-
elif
|
2571
|
-
flavor = "vm_aws"
|
2462
|
+
elif flavor == "vm_aws":
|
2572
2463
|
config["region"] = selected_orchestrator[1]
|
2573
|
-
elif
|
2574
|
-
|
2575
|
-
|
2576
|
-
|
2577
|
-
|
2578
|
-
config["location"] = query_gcp_region("Vertex AI job")
|
2579
|
-
elif selected_orchestrator[0] == "Kubernetes":
|
2580
|
-
flavor = "kubernetes"
|
2581
|
-
else:
|
2582
|
-
raise ValueError(
|
2583
|
-
f"Unknown orchestrator type {selected_orchestrator[0]}"
|
2464
|
+
elif flavor == "vm_gcp":
|
2465
|
+
config["region"] = query_region(
|
2466
|
+
StackDeploymentProvider.GCP,
|
2467
|
+
"Skypilot cluster",
|
2468
|
+
is_skypilot=True,
|
2584
2469
|
)
|
2585
|
-
|
2586
|
-
|
2587
|
-
|
2588
|
-
|
2589
|
-
|
2590
|
-
for each in service_connector_resource_models:
|
2591
|
-
if each.resource_type == "docker-registry":
|
2592
|
-
available_registries = each.resource_ids or []
|
2593
|
-
if not available_registries:
|
2594
|
-
cli_utils.error(
|
2595
|
-
"We were unable to find any container registries "
|
2596
|
-
"available to the service connector. Please, verify "
|
2597
|
-
"that needed permission are granted for the "
|
2598
|
-
f"service connector.\nDocumentation for the {registry_name} "
|
2599
|
-
"container registry resource configuration can "
|
2600
|
-
f"be found at {docs_link}"
|
2601
|
-
)
|
2602
|
-
return available_registries
|
2603
|
-
|
2604
|
-
if cloud_provider == "aws":
|
2605
|
-
flavor = "aws"
|
2606
|
-
available_registries = _get_registries(
|
2607
|
-
"ECR", f"{AWS_DOCS}#ecr-container-registry"
|
2470
|
+
elif flavor == "vm_azure":
|
2471
|
+
config["region"] = query_region(
|
2472
|
+
StackDeploymentProvider.AZURE,
|
2473
|
+
"Skypilot cluster",
|
2474
|
+
is_skypilot=True,
|
2608
2475
|
)
|
2609
|
-
|
2610
|
-
|
2611
|
-
|
2612
|
-
"GCR", f"{GCP_DOCS}#gcr-container-registry"
|
2476
|
+
elif flavor == "vertex":
|
2477
|
+
config["location"] = query_region(
|
2478
|
+
StackDeploymentProvider.GCP, "Vertex AI job"
|
2613
2479
|
)
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2480
|
+
service_connector_resource_id = selected_orchestrator[1]
|
2481
|
+
elif component_type == "container_registry":
|
2617
2482
|
selected_registry_idx = cli_utils.multi_choice_prompt(
|
2618
2483
|
object_type=f"{cloud_provider.upper()} registries",
|
2619
|
-
choices=
|
2620
|
-
headers=["Container Registry"],
|
2484
|
+
choices=choices,
|
2485
|
+
headers=["Container Registry Type", "Container Registry"],
|
2621
2486
|
prompt_text="Please choose one of the registries for the new container registry:",
|
2622
2487
|
)
|
2623
2488
|
if selected_registry_idx is None:
|
2624
2489
|
cli_utils.error("No container registry selected.")
|
2625
|
-
selected_registry =
|
2626
|
-
|
2627
|
-
|
2490
|
+
selected_registry = choices[selected_registry_idx]
|
2491
|
+
flavor = selected_registry[0]
|
2492
|
+
config = {"uri": selected_registry[1]}
|
2493
|
+
service_connector_resource_id = selected_registry[1]
|
2628
2494
|
else:
|
2629
2495
|
raise ValueError(f"Unknown component type {component_type}")
|
2630
2496
|
|
zenml/cli/stack_components.py
CHANGED
@@ -138,14 +138,16 @@ def generate_stack_component_describe_command(
|
|
138
138
|
|
139
139
|
if component_.connector:
|
140
140
|
# We also need the flavor to get the connector requirements
|
141
|
-
|
141
|
+
connector_requirements = client.get_flavor_by_name_and_type(
|
142
142
|
name=component_.flavor, component_type=component_type
|
143
|
-
)
|
143
|
+
).connector_requirements
|
144
|
+
else:
|
145
|
+
connector_requirements = None
|
144
146
|
|
145
147
|
cli_utils.print_stack_component_configuration(
|
146
148
|
component=component_,
|
147
149
|
active_status=component_.id == active_component_id,
|
148
|
-
connector_requirements=
|
150
|
+
connector_requirements=connector_requirements,
|
149
151
|
)
|
150
152
|
|
151
153
|
print_model_url(get_component_url(component_))
|
zenml/constants.py
CHANGED
@@ -173,6 +173,7 @@ ENV_ZENML_PIPELINE_API_TOKEN_EXPIRES_MINUTES = (
|
|
173
173
|
"ZENML_PIPELINE_API_TOKEN_EXPIRES_MINUTES"
|
174
174
|
)
|
175
175
|
ENV_ZENML_IGNORE_FAILURE_HOOK = "ZENML_IGNORE_FAILURE_HOOK"
|
176
|
+
ENV_ZENML_CUSTOM_SOURCE_ROOT = "ZENML_CUSTOM_SOURCE_ROOT"
|
176
177
|
|
177
178
|
# ZenML Server environment variables
|
178
179
|
ENV_ZENML_SERVER_PREFIX = "ZENML_SERVER_"
|
@@ -375,6 +376,7 @@ SERVICE_CONNECTOR_CLIENT = "/client"
|
|
375
376
|
SERVICE_CONNECTOR_RESOURCES = "/resources"
|
376
377
|
SERVICE_CONNECTOR_TYPES = "/service_connector_types"
|
377
378
|
SERVICE_CONNECTOR_VERIFY = "/verify"
|
379
|
+
SERVICE_CONNECTOR_FULL_STACK = "/full_stack_resources"
|
378
380
|
MODELS = "/models"
|
379
381
|
MODEL_VERSIONS = "/model_versions"
|
380
382
|
MODEL_VERSION_ARTIFACTS = "/model_version_artifacts"
|
@@ -392,6 +394,7 @@ STEPS = "/steps"
|
|
392
394
|
TAGS = "/tags"
|
393
395
|
TRIGGERS = "/triggers"
|
394
396
|
TRIGGER_EXECUTIONS = "/trigger_executions"
|
397
|
+
ONBOARDING_STATE = "/onboarding_state"
|
395
398
|
USERS = "/users"
|
396
399
|
URL = "/url"
|
397
400
|
VERSION_1 = "/v1"
|
zenml/enums.py
CHANGED
@@ -386,8 +386,24 @@ class PluginSubType(StrEnum):
|
|
386
386
|
PIPELINE_RUN = "pipeline_run"
|
387
387
|
|
388
388
|
|
389
|
+
class OnboardingStep(StrEnum):
|
390
|
+
"""All onboarding steps."""
|
391
|
+
|
392
|
+
DEVICE_VERIFIED = "device_verified"
|
393
|
+
PIPELINE_RUN = "pipeline_run"
|
394
|
+
STARTER_SETUP_COMPLETED = "starter_setup_completed"
|
395
|
+
STACK_WITH_REMOTE_ORCHESTRATOR_CREATED = (
|
396
|
+
"stack_with_remote_orchestrator_created"
|
397
|
+
)
|
398
|
+
PIPELINE_RUN_WITH_REMOTE_ORCHESTRATOR = (
|
399
|
+
"pipeline_run_with_remote_orchestrator"
|
400
|
+
)
|
401
|
+
PRODUCTION_SETUP_COMPLETED = "production_setup_completed"
|
402
|
+
|
403
|
+
|
389
404
|
class StackDeploymentProvider(StrEnum):
|
390
405
|
"""All possible stack deployment providers."""
|
391
406
|
|
392
407
|
AWS = "aws"
|
393
408
|
GCP = "gcp"
|
409
|
+
AZURE = "azure"
|