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.
Files changed (152) hide show
  1. README.md +2 -2
  2. RELEASE_NOTES.md +40 -0
  3. zenml/VERSION +1 -1
  4. zenml/__init__.py +2 -0
  5. zenml/cli/stack.py +114 -248
  6. zenml/cli/stack_components.py +5 -3
  7. zenml/constants.py +3 -0
  8. zenml/enums.py +16 -0
  9. zenml/integrations/__init__.py +1 -0
  10. zenml/integrations/azure/__init__.py +2 -2
  11. zenml/integrations/constants.py +1 -0
  12. zenml/integrations/databricks/__init__.py +52 -0
  13. zenml/integrations/databricks/flavors/__init__.py +30 -0
  14. zenml/integrations/databricks/flavors/databricks_model_deployer_flavor.py +118 -0
  15. zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +147 -0
  16. zenml/integrations/databricks/model_deployers/__init__.py +20 -0
  17. zenml/integrations/databricks/model_deployers/databricks_model_deployer.py +249 -0
  18. zenml/integrations/databricks/orchestrators/__init__.py +20 -0
  19. zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +497 -0
  20. zenml/integrations/databricks/orchestrators/databricks_orchestrator_entrypoint_config.py +97 -0
  21. zenml/integrations/databricks/services/__init__.py +19 -0
  22. zenml/integrations/databricks/services/databricks_deployment.py +407 -0
  23. zenml/integrations/databricks/utils/__init__.py +14 -0
  24. zenml/integrations/databricks/utils/databricks_utils.py +87 -0
  25. zenml/integrations/great_expectations/data_validators/ge_data_validator.py +12 -8
  26. zenml/integrations/huggingface/materializers/huggingface_datasets_materializer.py +88 -3
  27. zenml/integrations/huggingface/steps/accelerate_runner.py +1 -7
  28. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +1 -13
  29. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +22 -4
  30. zenml/integrations/kubernetes/pod_settings.py +4 -0
  31. zenml/integrations/lightgbm/__init__.py +1 -0
  32. zenml/integrations/mlflow/__init__.py +1 -1
  33. zenml/integrations/mlflow/model_registries/mlflow_model_registry.py +6 -2
  34. zenml/integrations/mlflow/services/mlflow_deployment.py +1 -1
  35. zenml/integrations/skypilot_azure/__init__.py +1 -3
  36. zenml/integrations/skypilot_lambda/__init__.py +1 -1
  37. zenml/logging/step_logging.py +34 -35
  38. zenml/materializers/built_in_materializer.py +1 -1
  39. zenml/materializers/cloudpickle_materializer.py +1 -1
  40. zenml/model/model.py +1 -1
  41. zenml/models/v2/core/component.py +29 -0
  42. zenml/models/v2/core/server_settings.py +0 -20
  43. zenml/models/v2/misc/full_stack.py +32 -0
  44. zenml/models/v2/misc/stack_deployment.py +5 -0
  45. zenml/new/pipelines/run_utils.py +1 -1
  46. zenml/orchestrators/__init__.py +4 -0
  47. zenml/orchestrators/step_launcher.py +1 -0
  48. zenml/orchestrators/wheeled_orchestrator.py +147 -0
  49. zenml/service_connectors/service_connector_utils.py +408 -0
  50. zenml/stack_deployments/azure_stack_deployment.py +179 -0
  51. zenml/stack_deployments/gcp_stack_deployment.py +13 -4
  52. zenml/stack_deployments/stack_deployment.py +10 -0
  53. zenml/stack_deployments/utils.py +4 -0
  54. zenml/steps/base_step.py +7 -5
  55. zenml/utils/function_utils.py +1 -1
  56. zenml/utils/pipeline_docker_image_builder.py +8 -0
  57. zenml/utils/source_utils.py +4 -1
  58. zenml/zen_server/dashboard/assets/{404-DpJaNHKF.js → 404-B_YdvmwS.js} +1 -1
  59. zenml/zen_server/dashboard/assets/{@reactflow-DJfzkHO1.js → @reactflow-l_1hUr1S.js} +1 -1
  60. zenml/zen_server/dashboard/assets/{AwarenessChannel-BYDLT2xC.js → AwarenessChannel-CFg5iX4Z.js} +1 -1
  61. zenml/zen_server/dashboard/assets/{CodeSnippet-BkOuRmyq.js → CodeSnippet-Dvkx_82E.js} +1 -1
  62. zenml/zen_server/dashboard/assets/CollapsibleCard-opiuBHHc.js +1 -0
  63. zenml/zen_server/dashboard/assets/{Commands-ZvWR1BRs.js → Commands-DoN1xrEq.js} +1 -1
  64. zenml/zen_server/dashboard/assets/{CopyButton-DVwLkafa.js → CopyButton-Cr7xYEPb.js} +1 -1
  65. zenml/zen_server/dashboard/assets/{CsvVizualization-C2IiqX4I.js → CsvVizualization-Ck-nZ43m.js} +3 -3
  66. zenml/zen_server/dashboard/assets/{Error-CqX0VqW_.js → Error-kLtljEOM.js} +1 -1
  67. zenml/zen_server/dashboard/assets/{ExecutionStatus-BoLUXR9t.js → ExecutionStatus-DguLLgTK.js} +1 -1
  68. zenml/zen_server/dashboard/assets/{Helpbox-LFydyVwh.js → Helpbox-BXUMP21n.js} +1 -1
  69. zenml/zen_server/dashboard/assets/{Infobox-DnENC0sh.js → Infobox-DSt0O-dm.js} +1 -1
  70. zenml/zen_server/dashboard/assets/{InlineAvatar-CbJtYr0t.js → InlineAvatar-xsrsIGE-.js} +1 -1
  71. zenml/zen_server/dashboard/assets/Pagination-C6X-mifw.js +1 -0
  72. zenml/zen_server/dashboard/assets/{SetPassword-BYBdbQDo.js → SetPassword-BXGTWiwj.js} +1 -1
  73. zenml/zen_server/dashboard/assets/{SuccessStep-Nx743hll.js → SuccessStep-DZC60t0x.js} +1 -1
  74. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DF9gSzE0.js → UpdatePasswordSchemas-DGvwFWO1.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{chevron-right-double-BiEMg7rd.js → chevron-right-double-CZBOf6JM.js} +1 -1
  76. zenml/zen_server/dashboard/assets/cloud-only-C_yFCAkP.js +1 -0
  77. zenml/zen_server/dashboard/assets/index-BczVOqUf.js +55 -0
  78. zenml/zen_server/dashboard/assets/index-EpMIKgrI.css +1 -0
  79. zenml/zen_server/dashboard/assets/{login-mutation-BUnVASxp.js → login-mutation-CrHrndTI.js} +1 -1
  80. zenml/zen_server/dashboard/assets/logs-D8k8BVFf.js +1 -0
  81. zenml/zen_server/dashboard/assets/{not-found-B4VnX8gK.js → not-found-DYa4pC-C.js} +1 -1
  82. zenml/zen_server/dashboard/assets/{package-CsUhPmou.js → package-B3fWP-Dh.js} +1 -1
  83. zenml/zen_server/dashboard/assets/page-1h_sD1jz.js +1 -0
  84. zenml/zen_server/dashboard/assets/{page-Sxn82W-5.js → page-1iL8aMqs.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{page-DMOYZppS.js → page-2grKx_MY.js} +1 -1
  86. zenml/zen_server/dashboard/assets/page-5NCOHOsy.js +1 -0
  87. zenml/zen_server/dashboard/assets/{page-JyfeDUfu.js → page-8a4UMKXZ.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{page-Bx6o0ARS.js → page-B6h3iaHJ.js} +1 -1
  89. zenml/zen_server/dashboard/assets/page-BDns21Iz.js +1 -0
  90. zenml/zen_server/dashboard/assets/{page-3efNCDeb.js → page-BhgCDInH.js} +2 -2
  91. zenml/zen_server/dashboard/assets/{page-DKlIdAe5.js → page-Bi-wtWiO.js} +2 -2
  92. zenml/zen_server/dashboard/assets/{page-7zTHbhhI.js → page-BkeAAYwp.js} +1 -1
  93. zenml/zen_server/dashboard/assets/{page-CRTJ0UuR.js → page-BkuQDIf-.js} +1 -1
  94. zenml/zen_server/dashboard/assets/page-BnaevhnB.js +1 -0
  95. zenml/zen_server/dashboard/assets/{page-BEs6jK71.js → page-Bq0YxkLV.js} +1 -1
  96. zenml/zen_server/dashboard/assets/page-Bs2F4eoD.js +2 -0
  97. zenml/zen_server/dashboard/assets/{page-CUZIGO-3.js → page-C6-UGEbH.js} +1 -1
  98. zenml/zen_server/dashboard/assets/{page-Xu8JEjSU.js → page-CCNRIt_f.js} +1 -1
  99. zenml/zen_server/dashboard/assets/{page-DvCvroOM.js → page-CHNxpz3n.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{page-BpSqIf4B.js → page-DgorQFqi.js} +1 -1
  101. zenml/zen_server/dashboard/assets/page-K8ebxVIs.js +1 -0
  102. zenml/zen_server/dashboard/assets/{page-Cx67M0QT.js → page-MFQyIJd3.js} +1 -1
  103. zenml/zen_server/dashboard/assets/page-TgCF0P_U.js +1 -0
  104. zenml/zen_server/dashboard/assets/page-ZnCEe-eK.js +9 -0
  105. zenml/zen_server/dashboard/assets/{page-Dc_7KMQE.js → page-uA5prJGY.js} +1 -1
  106. zenml/zen_server/dashboard/assets/persist-D7HJNBWx.js +1 -0
  107. zenml/zen_server/dashboard/assets/plus-C8WOyCzt.js +1 -0
  108. zenml/zen_server/dashboard/assets/stack-detail-query-Cficsl6d.js +1 -0
  109. zenml/zen_server/dashboard/assets/update-server-settings-mutation-7d8xi1tS.js +1 -0
  110. zenml/zen_server/dashboard/assets/{url-DuQMeqYA.js → url-D7mAQGUM.js} +1 -1
  111. zenml/zen_server/dashboard/index.html +4 -4
  112. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  113. zenml/zen_server/dashboard_legacy/index.html +1 -1
  114. zenml/zen_server/dashboard_legacy/{precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js → precache-manifest.12246c7548e71e2c4438e496360de80c.js} +4 -4
  115. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  116. zenml/zen_server/dashboard_legacy/static/js/main.3b27024b.chunk.js +2 -0
  117. zenml/zen_server/dashboard_legacy/static/js/{main.382439a7.chunk.js.map → main.3b27024b.chunk.js.map} +1 -1
  118. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  119. zenml/zen_server/deploy/helm/README.md +2 -2
  120. zenml/zen_server/rbac/utils.py +10 -2
  121. zenml/zen_server/routers/devices_endpoints.py +4 -1
  122. zenml/zen_server/routers/server_endpoints.py +29 -2
  123. zenml/zen_server/routers/service_connectors_endpoints.py +57 -0
  124. zenml/zen_server/routers/steps_endpoints.py +2 -1
  125. zenml/zen_stores/migrations/versions/0.62.0_release.py +23 -0
  126. zenml/zen_stores/migrations/versions/b4fca5241eea_migrate_onboarding_state.py +167 -0
  127. zenml/zen_stores/rest_zen_store.py +4 -0
  128. zenml/zen_stores/schemas/component_schemas.py +14 -0
  129. zenml/zen_stores/schemas/server_settings_schemas.py +23 -11
  130. zenml/zen_stores/sql_zen_store.py +151 -1
  131. {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/METADATA +5 -5
  132. {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/RECORD +135 -115
  133. zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +0 -1
  134. zenml/zen_server/dashboard/assets/chevron-down-D_ZlKMqH.js +0 -1
  135. zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +0 -1
  136. zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +0 -1
  137. zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +0 -55
  138. zenml/zen_server/dashboard/assets/index-inApY3KQ.css +0 -1
  139. zenml/zen_server/dashboard/assets/page-C43QGHTt.js +0 -9
  140. zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +0 -1
  141. zenml/zen_server/dashboard/assets/page-CaopxiU1.js +0 -1
  142. zenml/zen_server/dashboard/assets/page-D7Z399xy.js +0 -1
  143. zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +0 -1
  144. zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +0 -2
  145. zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +0 -1
  146. zenml/zen_server/dashboard/assets/page-TKXERe16.js +0 -1
  147. zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +0 -1
  148. zenml/zen_server/dashboard/assets/update-server-settings-mutation-CR8e3Sir.js +0 -1
  149. zenml/zen_server/dashboard_legacy/static/js/main.382439a7.chunk.js +0 -2
  150. {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/LICENSE +0 -0
  151. {zenml_nightly-0.61.0.dev20240712.dist-info → zenml_nightly-0.62.0.dev20240726.dist-info}/WHEEL +0 -0
  152. {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/cloud">Sign up for ZenML Pro</a>
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.61.0 is out. Check out the release notes
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.61.0.dev20240712
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.models.v2.misc.service_connector_type import (
88
- ServiceConnectorTypedResourcesModel,
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
- service_connector_resource_model = None
394
- can_generate_long_tokens = False
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
- existing_components = client.list_stack_components(
412
- type=component_type.value,
413
- connector_id=service_connector,
414
- size=100,
415
- )
416
- # if some existing components are found - prompt user what to do
417
- component_selected: Optional[int] = None
418
- if existing_components.total > 0:
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
- [component.name]
423
- for component in existing_components.items
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
- service_connector_resource_models=service_connector_resource_model.resources,
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.items[
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:\n"
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
- service_connector_resource_models: List[
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
- service_connector_resource_models: The list of the available service connector resource models.
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=[[st] for st in available_storages],
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 = available_storages[selected_storage_idx]
2420
+ selected_storage = choices[selected_storage_idx]
2476
2421
 
2477
- config = {"path": selected_storage}
2478
- service_connector_resource_id = selected_storage
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 query_gcp_region(compute_type: str) -> str:
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
- Client()
2486
- .zen_store.get_stack_deployment_info(
2487
- StackDeploymentProvider.GCP
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=available_orchestrators,
2555
- headers=["Orchestrator Type", "Orchestrator details"],
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 = available_orchestrators[
2562
- selected_orchestrator_idx
2563
- ]
2455
+ selected_orchestrator = choices[selected_orchestrator_idx]
2564
2456
 
2565
2457
  config = {}
2566
- if selected_orchestrator[0] == "Sagemaker":
2567
- flavor = "sagemaker"
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 selected_orchestrator[0] == "Skypilot (EC2)":
2571
- flavor = "vm_aws"
2462
+ elif flavor == "vm_aws":
2572
2463
  config["region"] = selected_orchestrator[1]
2573
- elif selected_orchestrator[0] == "Skypilot (Compute)":
2574
- flavor = "vm_gcp"
2575
- config["region"] = query_gcp_region("Skypilot cluster")
2576
- elif selected_orchestrator[0] == "Vertex AI":
2577
- flavor = "vertex"
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
- service_connector_resource_id = selected_orchestrator[1]
2586
- elif component_type == "container_registry":
2587
-
2588
- def _get_registries(registry_name: str, docs_link: str) -> List[str]:
2589
- available_registries: List[str] = []
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
- if cloud_provider == "gcp":
2610
- flavor = "gcp"
2611
- available_registries = _get_registries(
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
- if cloud_provider == "azure":
2615
- flavor = "azure"
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=[[st] for st in available_registries],
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 = available_registries[selected_registry_idx]
2626
- config = {"uri": selected_registry}
2627
- service_connector_resource_id = selected_registry
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
 
@@ -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
- flavor = client.get_flavor_by_name_and_type(
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=flavor.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"