zenml-nightly 0.61.0.dev20240713__py3-none-any.whl → 0.62.0.dev20240717__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 (131) hide show
  1. README.md +1 -1
  2. RELEASE_NOTES.md +40 -0
  3. zenml/VERSION +1 -1
  4. zenml/__init__.py +2 -0
  5. zenml/cli/stack.py +87 -228
  6. zenml/cli/stack_components.py +5 -3
  7. zenml/constants.py +2 -0
  8. zenml/entrypoints/entrypoint.py +3 -1
  9. zenml/integrations/__init__.py +1 -0
  10. zenml/integrations/constants.py +1 -0
  11. zenml/integrations/databricks/__init__.py +52 -0
  12. zenml/integrations/databricks/flavors/__init__.py +30 -0
  13. zenml/integrations/databricks/flavors/databricks_model_deployer_flavor.py +118 -0
  14. zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +147 -0
  15. zenml/integrations/databricks/model_deployers/__init__.py +20 -0
  16. zenml/integrations/databricks/model_deployers/databricks_model_deployer.py +249 -0
  17. zenml/integrations/databricks/orchestrators/__init__.py +20 -0
  18. zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +498 -0
  19. zenml/integrations/databricks/orchestrators/databricks_orchestrator_entrypoint_config.py +97 -0
  20. zenml/integrations/databricks/services/__init__.py +19 -0
  21. zenml/integrations/databricks/services/databricks_deployment.py +407 -0
  22. zenml/integrations/databricks/utils/__init__.py +14 -0
  23. zenml/integrations/databricks/utils/databricks_utils.py +87 -0
  24. zenml/integrations/great_expectations/data_validators/ge_data_validator.py +12 -8
  25. zenml/integrations/huggingface/materializers/huggingface_datasets_materializer.py +88 -3
  26. zenml/integrations/huggingface/steps/accelerate_runner.py +1 -7
  27. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +7 -0
  28. zenml/integrations/kubernetes/pod_settings.py +2 -0
  29. zenml/integrations/lightgbm/__init__.py +1 -0
  30. zenml/integrations/mlflow/__init__.py +1 -1
  31. zenml/integrations/mlflow/model_registries/mlflow_model_registry.py +6 -2
  32. zenml/integrations/mlflow/services/mlflow_deployment.py +1 -1
  33. zenml/integrations/skypilot_lambda/__init__.py +1 -1
  34. zenml/materializers/built_in_materializer.py +1 -1
  35. zenml/materializers/cloudpickle_materializer.py +1 -1
  36. zenml/model/model.py +1 -1
  37. zenml/models/v2/misc/full_stack.py +32 -0
  38. zenml/orchestrators/__init__.py +4 -0
  39. zenml/orchestrators/wheeled_orchestrator.py +147 -0
  40. zenml/service_connectors/service_connector_utils.py +349 -0
  41. zenml/stack_deployments/gcp_stack_deployment.py +2 -4
  42. zenml/steps/base_step.py +7 -5
  43. zenml/utils/function_utils.py +1 -1
  44. zenml/utils/pipeline_docker_image_builder.py +8 -0
  45. zenml/zen_server/dashboard/assets/{404-DpJaNHKF.js → 404-B_YdvmwS.js} +1 -1
  46. zenml/zen_server/dashboard/assets/{@reactflow-DJfzkHO1.js → @reactflow-l_1hUr1S.js} +1 -1
  47. zenml/zen_server/dashboard/assets/{AwarenessChannel-BYDLT2xC.js → AwarenessChannel-CFg5iX4Z.js} +1 -1
  48. zenml/zen_server/dashboard/assets/{CodeSnippet-BkOuRmyq.js → CodeSnippet-Dvkx_82E.js} +1 -1
  49. zenml/zen_server/dashboard/assets/CollapsibleCard-opiuBHHc.js +1 -0
  50. zenml/zen_server/dashboard/assets/{Commands-ZvWR1BRs.js → Commands-DoN1xrEq.js} +1 -1
  51. zenml/zen_server/dashboard/assets/{CopyButton-DVwLkafa.js → CopyButton-Cr7xYEPb.js} +1 -1
  52. zenml/zen_server/dashboard/assets/{CsvVizualization-C2IiqX4I.js → CsvVizualization-Ck-nZ43m.js} +3 -3
  53. zenml/zen_server/dashboard/assets/{Error-CqX0VqW_.js → Error-kLtljEOM.js} +1 -1
  54. zenml/zen_server/dashboard/assets/{ExecutionStatus-BoLUXR9t.js → ExecutionStatus-DguLLgTK.js} +1 -1
  55. zenml/zen_server/dashboard/assets/{Helpbox-LFydyVwh.js → Helpbox-BXUMP21n.js} +1 -1
  56. zenml/zen_server/dashboard/assets/{Infobox-DnENC0sh.js → Infobox-DSt0O-dm.js} +1 -1
  57. zenml/zen_server/dashboard/assets/{InlineAvatar-CbJtYr0t.js → InlineAvatar-xsrsIGE-.js} +1 -1
  58. zenml/zen_server/dashboard/assets/Pagination-C6X-mifw.js +1 -0
  59. zenml/zen_server/dashboard/assets/{SetPassword-BYBdbQDo.js → SetPassword-BXGTWiwj.js} +1 -1
  60. zenml/zen_server/dashboard/assets/{SuccessStep-Nx743hll.js → SuccessStep-DZC60t0x.js} +1 -1
  61. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DF9gSzE0.js → UpdatePasswordSchemas-DGvwFWO1.js} +1 -1
  62. zenml/zen_server/dashboard/assets/{chevron-right-double-BiEMg7rd.js → chevron-right-double-CZBOf6JM.js} +1 -1
  63. zenml/zen_server/dashboard/assets/cloud-only-C_yFCAkP.js +1 -0
  64. zenml/zen_server/dashboard/assets/index-BczVOqUf.js +55 -0
  65. zenml/zen_server/dashboard/assets/index-EpMIKgrI.css +1 -0
  66. zenml/zen_server/dashboard/assets/{login-mutation-BUnVASxp.js → login-mutation-CrHrndTI.js} +1 -1
  67. zenml/zen_server/dashboard/assets/logs-D8k8BVFf.js +1 -0
  68. zenml/zen_server/dashboard/assets/{not-found-B4VnX8gK.js → not-found-DYa4pC-C.js} +1 -1
  69. zenml/zen_server/dashboard/assets/{package-CsUhPmou.js → package-B3fWP-Dh.js} +1 -1
  70. zenml/zen_server/dashboard/assets/page-1h_sD1jz.js +1 -0
  71. zenml/zen_server/dashboard/assets/{page-Sxn82W-5.js → page-1iL8aMqs.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{page-DMOYZppS.js → page-2grKx_MY.js} +1 -1
  73. zenml/zen_server/dashboard/assets/page-5NCOHOsy.js +1 -0
  74. zenml/zen_server/dashboard/assets/{page-JyfeDUfu.js → page-8a4UMKXZ.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{page-Bx6o0ARS.js → page-B6h3iaHJ.js} +1 -1
  76. zenml/zen_server/dashboard/assets/page-BDns21Iz.js +1 -0
  77. zenml/zen_server/dashboard/assets/{page-3efNCDeb.js → page-BhgCDInH.js} +2 -2
  78. zenml/zen_server/dashboard/assets/{page-DKlIdAe5.js → page-Bi-wtWiO.js} +2 -2
  79. zenml/zen_server/dashboard/assets/{page-7zTHbhhI.js → page-BkeAAYwp.js} +1 -1
  80. zenml/zen_server/dashboard/assets/{page-CRTJ0UuR.js → page-BkuQDIf-.js} +1 -1
  81. zenml/zen_server/dashboard/assets/page-BnaevhnB.js +1 -0
  82. zenml/zen_server/dashboard/assets/{page-BEs6jK71.js → page-Bq0YxkLV.js} +1 -1
  83. zenml/zen_server/dashboard/assets/page-Bs2F4eoD.js +2 -0
  84. zenml/zen_server/dashboard/assets/{page-CUZIGO-3.js → page-C6-UGEbH.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{page-Xu8JEjSU.js → page-CCNRIt_f.js} +1 -1
  86. zenml/zen_server/dashboard/assets/{page-DvCvroOM.js → page-CHNxpz3n.js} +1 -1
  87. zenml/zen_server/dashboard/assets/{page-BpSqIf4B.js → page-DgorQFqi.js} +1 -1
  88. zenml/zen_server/dashboard/assets/page-K8ebxVIs.js +1 -0
  89. zenml/zen_server/dashboard/assets/{page-Cx67M0QT.js → page-MFQyIJd3.js} +1 -1
  90. zenml/zen_server/dashboard/assets/page-TgCF0P_U.js +1 -0
  91. zenml/zen_server/dashboard/assets/page-ZnCEe-eK.js +9 -0
  92. zenml/zen_server/dashboard/assets/{page-Dc_7KMQE.js → page-uA5prJGY.js} +1 -1
  93. zenml/zen_server/dashboard/assets/persist-D7HJNBWx.js +1 -0
  94. zenml/zen_server/dashboard/assets/plus-C8WOyCzt.js +1 -0
  95. zenml/zen_server/dashboard/assets/stack-detail-query-Cficsl6d.js +1 -0
  96. zenml/zen_server/dashboard/assets/update-server-settings-mutation-7d8xi1tS.js +1 -0
  97. zenml/zen_server/dashboard/assets/{url-DuQMeqYA.js → url-D7mAQGUM.js} +1 -1
  98. zenml/zen_server/dashboard/index.html +4 -4
  99. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  100. zenml/zen_server/dashboard_legacy/index.html +1 -1
  101. zenml/zen_server/dashboard_legacy/{precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js → precache-manifest.12246c7548e71e2c4438e496360de80c.js} +4 -4
  102. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  103. zenml/zen_server/dashboard_legacy/static/js/main.3b27024b.chunk.js +2 -0
  104. zenml/zen_server/dashboard_legacy/static/js/{main.382439a7.chunk.js.map → main.3b27024b.chunk.js.map} +1 -1
  105. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  106. zenml/zen_server/deploy/helm/README.md +2 -2
  107. zenml/zen_server/routers/service_connectors_endpoints.py +57 -0
  108. zenml/zen_stores/migrations/versions/0.62.0_release.py +23 -0
  109. zenml/zen_stores/rest_zen_store.py +4 -0
  110. {zenml_nightly-0.61.0.dev20240713.dist-info → zenml_nightly-0.62.0.dev20240717.dist-info}/METADATA +2 -2
  111. {zenml_nightly-0.61.0.dev20240713.dist-info → zenml_nightly-0.62.0.dev20240717.dist-info}/RECORD +114 -96
  112. zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +0 -1
  113. zenml/zen_server/dashboard/assets/chevron-down-D_ZlKMqH.js +0 -1
  114. zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +0 -1
  115. zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +0 -1
  116. zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +0 -55
  117. zenml/zen_server/dashboard/assets/index-inApY3KQ.css +0 -1
  118. zenml/zen_server/dashboard/assets/page-C43QGHTt.js +0 -9
  119. zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +0 -1
  120. zenml/zen_server/dashboard/assets/page-CaopxiU1.js +0 -1
  121. zenml/zen_server/dashboard/assets/page-D7Z399xy.js +0 -1
  122. zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +0 -1
  123. zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +0 -2
  124. zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +0 -1
  125. zenml/zen_server/dashboard/assets/page-TKXERe16.js +0 -1
  126. zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +0 -1
  127. zenml/zen_server/dashboard/assets/update-server-settings-mutation-CR8e3Sir.js +0 -1
  128. zenml/zen_server/dashboard_legacy/static/js/main.382439a7.chunk.js +0 -2
  129. {zenml_nightly-0.61.0.dev20240713.dist-info → zenml_nightly-0.62.0.dev20240717.dist-info}/LICENSE +0 -0
  130. {zenml_nightly-0.61.0.dev20240713.dist-info → zenml_nightly-0.62.0.dev20240717.dist-info}/WHEEL +0 -0
  131. {zenml_nightly-0.61.0.dev20240713.dist-info → zenml_nightly-0.62.0.dev20240717.dist-info}/entry_points.txt +0 -0
README.md CHANGED
@@ -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.dev20240713
1
+ 0.62.0.dev20240717
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
@@ -1752,12 +1745,12 @@ def deploy(
1752
1745
  Markdown(
1753
1746
  "## Configuration\n"
1754
1747
  "You will be asked to provide the following configuration "
1755
- "values during the deployment process:\n"
1756
- )
1748
+ "values during the deployment process:"
1749
+ ),
1750
+ "\n",
1757
1751
  )
1758
1752
 
1759
1753
  console.print(
1760
- "\n",
1761
1754
  deployment_config.configuration,
1762
1755
  no_wrap=True,
1763
1756
  overflow="ignore",
@@ -2349,7 +2342,7 @@ def _get_service_connector_info(
2349
2342
  choices.append([value.name, required])
2350
2343
 
2351
2344
  selected_auth_idx = cli_utils.multi_choice_prompt(
2352
- object_type=f"authentication methods for {cloud_provider}",
2345
+ object_type=f"authentication methods for {cloud_provider.upper()}",
2353
2346
  choices=choices,
2354
2347
  headers=headers,
2355
2348
  prompt_text="Please choose one of the authentication option above",
@@ -2393,10 +2386,7 @@ def _get_service_connector_info(
2393
2386
  def _get_stack_component_info(
2394
2387
  component_type: str,
2395
2388
  cloud_provider: str,
2396
- service_connector_resource_models: List[
2397
- ServiceConnectorTypedResourcesModel
2398
- ],
2399
- can_generate_long_tokens: bool,
2389
+ resources_info: ServiceConnectorResourcesInfo,
2400
2390
  service_connector_index: Optional[int] = None,
2401
2391
  ) -> ComponentInfo:
2402
2392
  """Get a stack component info with given type and service connector.
@@ -2404,8 +2394,7 @@ def _get_stack_component_info(
2404
2394
  Args:
2405
2395
  component_type: The type of component to create.
2406
2396
  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.
2397
+ resources_info: The resources info of the service connector.
2409
2398
  service_connector_index: The index of the service connector to use.
2410
2399
 
2411
2400
  Returns:
@@ -2420,62 +2409,30 @@ def _get_stack_component_info(
2420
2409
  if cloud_provider not in {"aws", "azure", "gcp"}:
2421
2410
  raise ValueError(f"Unknown cloud provider {cloud_provider}")
2422
2411
 
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
2412
  flavor = "undefined"
2431
2413
  service_connector_resource_id = None
2432
2414
  config = {}
2415
+ choices = [
2416
+ [cri.flavor, resource_id]
2417
+ for cri in resources_info.components_resources_info[
2418
+ StackComponentType(component_type)
2419
+ ]
2420
+ for resource_id in cri.accessible_by_service_connector
2421
+ ]
2433
2422
  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
2423
  selected_storage_idx = cli_utils.multi_choice_prompt(
2467
2424
  object_type=f"{cloud_provider.upper()} storages",
2468
- choices=[[st] for st in available_storages],
2469
- headers=["Storage"],
2425
+ choices=choices,
2426
+ headers=["Artifact Store Type", "Storage"],
2470
2427
  prompt_text="Please choose one of the storages for the new artifact store:",
2471
2428
  )
2472
2429
  if selected_storage_idx is None:
2473
2430
  cli_utils.error("No storage selected.")
2474
2431
 
2475
- selected_storage = available_storages[selected_storage_idx]
2432
+ selected_storage = choices[selected_storage_idx]
2476
2433
 
2477
- config = {"path": selected_storage}
2478
- service_connector_resource_id = selected_storage
2434
+ config = {"path": selected_storage[1]}
2435
+ service_connector_resource_id = selected_storage[1]
2479
2436
  elif component_type == "orchestrator":
2480
2437
 
2481
2438
  def query_gcp_region(compute_type: str) -> str:
@@ -2492,139 +2449,41 @@ def _get_stack_component_info(
2492
2449
  )
2493
2450
  return region
2494
2451
 
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
2452
  selected_orchestrator_idx = cli_utils.multi_choice_prompt(
2553
2453
  object_type=f"orchestrators on {cloud_provider.upper()}",
2554
- choices=available_orchestrators,
2555
- headers=["Orchestrator Type", "Orchestrator details"],
2454
+ choices=choices,
2455
+ headers=["Orchestrator Type", "Details"],
2556
2456
  prompt_text="Please choose one of the orchestrators for the new orchestrator:",
2557
2457
  )
2558
2458
  if selected_orchestrator_idx is None:
2559
2459
  cli_utils.error("No orchestrator selected.")
2560
2460
 
2561
- selected_orchestrator = available_orchestrators[
2562
- selected_orchestrator_idx
2563
- ]
2461
+ selected_orchestrator = choices[selected_orchestrator_idx]
2564
2462
 
2565
2463
  config = {}
2566
- if selected_orchestrator[0] == "Sagemaker":
2567
- flavor = "sagemaker"
2464
+ flavor = selected_orchestrator[0]
2465
+ if flavor == "sagemaker":
2568
2466
  execution_role = Prompt.ask("Enter an execution role ARN:")
2569
2467
  config["execution_role"] = execution_role
2570
- elif selected_orchestrator[0] == "Skypilot (EC2)":
2571
- flavor = "vm_aws"
2468
+ elif flavor == "vm_aws":
2572
2469
  config["region"] = selected_orchestrator[1]
2573
- elif selected_orchestrator[0] == "Skypilot (Compute)":
2574
- flavor = "vm_gcp"
2470
+ elif flavor == "vm_azure":
2575
2471
  config["region"] = query_gcp_region("Skypilot cluster")
2576
- elif selected_orchestrator[0] == "Vertex AI":
2577
- flavor = "vertex"
2472
+ elif flavor == "vertex":
2578
2473
  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]}"
2584
- )
2585
2474
  service_connector_resource_id = selected_orchestrator[1]
2586
2475
  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"
2608
- )
2609
- if cloud_provider == "gcp":
2610
- flavor = "gcp"
2611
- available_registries = _get_registries(
2612
- "GCR", f"{GCP_DOCS}#gcr-container-registry"
2613
- )
2614
- if cloud_provider == "azure":
2615
- flavor = "azure"
2616
-
2617
2476
  selected_registry_idx = cli_utils.multi_choice_prompt(
2618
2477
  object_type=f"{cloud_provider.upper()} registries",
2619
- choices=[[st] for st in available_registries],
2620
- headers=["Container Registry"],
2478
+ choices=choices,
2479
+ headers=["Container Registry Type", "Container Registry"],
2621
2480
  prompt_text="Please choose one of the registries for the new container registry:",
2622
2481
  )
2623
2482
  if selected_registry_idx is None:
2624
2483
  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
2484
+ selected_registry = choices[selected_registry_idx]
2485
+ config = {"uri": selected_registry[1]}
2486
+ service_connector_resource_id = selected_registry[1]
2628
2487
  else:
2629
2488
  raise ValueError(f"Unknown component type {component_type}")
2630
2489
 
@@ -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"
@@ -15,6 +15,7 @@
15
15
 
16
16
  import argparse
17
17
  import logging
18
+ import os
18
19
  import sys
19
20
 
20
21
  from zenml import constants
@@ -44,7 +45,8 @@ def main() -> None:
44
45
  parser = argparse.ArgumentParser()
45
46
  parser.add_argument(f"--{ENTRYPOINT_CONFIG_SOURCE_OPTION}", required=True)
46
47
  args, remaining_args = parser.parse_known_args()
47
-
48
+ if os.environ.get(constants.ENV_ZENML_CUSTOM_SOURCE_ROOT):
49
+ source_utils.set_custom_source_root(source_root=os.getcwd())
48
50
  entrypoint_config_class = source_utils.load_and_validate_class(
49
51
  args.entrypoint_config_source,
50
52
  expected_class=BaseEntrypointConfiguration,
@@ -23,6 +23,7 @@ from zenml.integrations.aws import AWSIntegration # noqa
23
23
  from zenml.integrations.azure import AzureIntegration # noqa
24
24
  from zenml.integrations.bentoml import BentoMLIntegration # noqa
25
25
  from zenml.integrations.bitbucket import BitbucketIntegration # noqa
26
+ from zenml.integrations.databricks import DatabricksIntegration # noqa
26
27
  from zenml.integrations.comet import CometIntegration # noqa
27
28
  from zenml.integrations.deepchecks import DeepchecksIntegration # noqa
28
29
  from zenml.integrations.discord import DiscordIntegration # noqa
@@ -22,6 +22,7 @@ BENTOML = "bentoml"
22
22
  BITBUCKET = "bitbucket"
23
23
  COMET = "comet"
24
24
  DASH = "dash"
25
+ DATABRICKS = "databricks"
25
26
  DEEPCHECKS = "deepchecks"
26
27
  DISCORD = "discord"
27
28
  EVIDENTLY = "evidently"
@@ -0,0 +1,52 @@
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
+ """Initialization of the Databricks integration for ZenML."""
15
+
16
+ from typing import List, Type
17
+
18
+ from zenml.integrations.constants import (
19
+ DATABRICKS,
20
+ )
21
+ from zenml.integrations.integration import Integration
22
+ from zenml.stack import Flavor
23
+
24
+ DATABRICKS_ORCHESTRATOR_FLAVOR = "databricks"
25
+ DATABRICKS_MODEL_DEPLOYER_FLAVOR = "databricks"
26
+ DATABRICKS_SERVICE_ARTIFACT = "databricks_deployment_service"
27
+
28
+
29
+ class DatabricksIntegration(Integration):
30
+ """Definition of Databricks Integration for ZenML."""
31
+
32
+ NAME = DATABRICKS
33
+ REQUIREMENTS = ["databricks-sdk==0.28.0"]
34
+
35
+ @classmethod
36
+ def flavors(cls) -> List[Type[Flavor]]:
37
+ """Declare the stack component flavors for the Databricks integration.
38
+
39
+ Returns:
40
+ List of stack component flavors for this integration.
41
+ """
42
+ from zenml.integrations.databricks.flavors import (
43
+ DatabricksOrchestratorFlavor,
44
+ DatabricksModelDeployerFlavor,
45
+ )
46
+
47
+ return [
48
+ DatabricksOrchestratorFlavor,
49
+ DatabricksModelDeployerFlavor,
50
+ ]
51
+
52
+ DatabricksIntegration.check_installation()