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
@@ -20,8 +20,8 @@ ZenML is an open-source MLOps framework designed to help you create robust, main
|
|
20
20
|
To install the ZenML chart directly from Amazon ECR, use the following command:
|
21
21
|
|
22
22
|
```bash
|
23
|
-
# example command for version 0.
|
24
|
-
helm install my-zenml oci://public.ecr.aws/zenml/zenml --version 0.
|
23
|
+
# example command for version 0.62.0
|
24
|
+
helm install my-zenml oci://public.ecr.aws/zenml/zenml --version 0.62.0
|
25
25
|
```
|
26
26
|
|
27
27
|
Note: Ensure you have OCI support enabled in your Helm client and that you are authenticated with Amazon ECR.
|
zenml/zen_server/rbac/utils.py
CHANGED
@@ -103,7 +103,9 @@ def dehydrate_response_model(
|
|
103
103
|
)
|
104
104
|
|
105
105
|
dehydrated_values = {}
|
106
|
-
for
|
106
|
+
# See `get_subresources_for_model(...)` for a detailed explanation why we
|
107
|
+
# need to use `model.__iter__()` here
|
108
|
+
for key, value in model.__iter__():
|
107
109
|
dehydrated_values[key] = _dehydrate_value(
|
108
110
|
value, permissions=permissions
|
109
111
|
)
|
@@ -484,7 +486,13 @@ def get_subresources_for_model(
|
|
484
486
|
"""
|
485
487
|
resources = set()
|
486
488
|
|
487
|
-
|
489
|
+
# We don't want to use `model.model_dump()` here as that recursively
|
490
|
+
# converts models to dicts, but we want to preserve those classes for
|
491
|
+
# the recursive `_get_subresources_for_value` calls.
|
492
|
+
# We previously used `dict(model)` here, but that lead to issues with
|
493
|
+
# models overwriting `__getattr__`, this `model.__iter__()` has the same
|
494
|
+
# results though.
|
495
|
+
for _, value in model.__iter__():
|
488
496
|
resources.update(_get_subresources_for_value(value))
|
489
497
|
|
490
498
|
return resources
|
@@ -27,7 +27,7 @@ from zenml.constants import (
|
|
27
27
|
DEVICES,
|
28
28
|
VERSION_1,
|
29
29
|
)
|
30
|
-
from zenml.enums import OAuthDeviceStatus
|
30
|
+
from zenml.enums import OAuthDeviceStatus, OnboardingStep
|
31
31
|
from zenml.models import (
|
32
32
|
OAuthDeviceFilter,
|
33
33
|
OAuthDeviceInternalUpdate,
|
@@ -270,6 +270,9 @@ def verify_authorized_device(
|
|
270
270
|
update=update,
|
271
271
|
)
|
272
272
|
|
273
|
+
store.update_onboarding_state(
|
274
|
+
completed_steps={OnboardingStep.DEVICE_VERIFIED}
|
275
|
+
)
|
273
276
|
return device_model
|
274
277
|
|
275
278
|
|
@@ -13,12 +13,19 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for authentication (login)."""
|
15
15
|
|
16
|
-
from typing import Optional
|
16
|
+
from typing import List, Optional
|
17
17
|
|
18
18
|
from fastapi import APIRouter, Security
|
19
19
|
|
20
20
|
import zenml
|
21
|
-
from zenml.constants import
|
21
|
+
from zenml.constants import (
|
22
|
+
ACTIVATE,
|
23
|
+
API,
|
24
|
+
INFO,
|
25
|
+
ONBOARDING_STATE,
|
26
|
+
SERVER_SETTINGS,
|
27
|
+
VERSION_1,
|
28
|
+
)
|
22
29
|
from zenml.enums import AuthScheme
|
23
30
|
from zenml.exceptions import IllegalOperationError
|
24
31
|
from zenml.models import (
|
@@ -64,6 +71,26 @@ def server_info() -> ServerModel:
|
|
64
71
|
return zen_store().get_store_info()
|
65
72
|
|
66
73
|
|
74
|
+
@router.get(
|
75
|
+
ONBOARDING_STATE,
|
76
|
+
responses={
|
77
|
+
401: error_response,
|
78
|
+
404: error_response,
|
79
|
+
422: error_response,
|
80
|
+
},
|
81
|
+
)
|
82
|
+
@handle_exceptions
|
83
|
+
def get_onboarding_state(
|
84
|
+
_: AuthContext = Security(authorize),
|
85
|
+
) -> List[str]:
|
86
|
+
"""Get the onboarding state of the server.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
The onboarding state of the server.
|
90
|
+
"""
|
91
|
+
return zen_store().get_onboarding_state()
|
92
|
+
|
93
|
+
|
67
94
|
# We don't have any concrete value that tells us whether a server is a cloud
|
68
95
|
# tenant, so we use `external_server_id` as the best proxy option.
|
69
96
|
# For cloud tenants, we don't add these endpoints as the server settings don't
|
@@ -21,6 +21,7 @@ from fastapi import APIRouter, Depends, Security
|
|
21
21
|
from zenml.constants import (
|
22
22
|
API,
|
23
23
|
SERVICE_CONNECTOR_CLIENT,
|
24
|
+
SERVICE_CONNECTOR_FULL_STACK,
|
24
25
|
SERVICE_CONNECTOR_TYPES,
|
25
26
|
SERVICE_CONNECTOR_VERIFY,
|
26
27
|
SERVICE_CONNECTORS,
|
@@ -35,6 +36,13 @@ from zenml.models import (
|
|
35
36
|
ServiceConnectorTypeModel,
|
36
37
|
ServiceConnectorUpdate,
|
37
38
|
)
|
39
|
+
from zenml.models.v2.misc.full_stack import (
|
40
|
+
ServiceConnectorInfo,
|
41
|
+
ServiceConnectorResourcesInfo,
|
42
|
+
)
|
43
|
+
from zenml.service_connectors.service_connector_utils import (
|
44
|
+
get_resources_options_from_resource_model_for_full_stack,
|
45
|
+
)
|
38
46
|
from zenml.zen_server.auth import AuthContext, authorize
|
39
47
|
from zenml.zen_server.exceptions import error_response
|
40
48
|
from zenml.zen_server.rbac.endpoint_utils import (
|
@@ -393,3 +401,52 @@ def get_service_connector_type(
|
|
393
401
|
The requested service connector type.
|
394
402
|
"""
|
395
403
|
return zen_store().get_service_connector_type(connector_type)
|
404
|
+
|
405
|
+
|
406
|
+
@router.post(
|
407
|
+
SERVICE_CONNECTOR_FULL_STACK,
|
408
|
+
responses={401: error_response, 409: error_response, 422: error_response},
|
409
|
+
)
|
410
|
+
@handle_exceptions
|
411
|
+
def get_resources_based_on_service_connector_info(
|
412
|
+
connector_info: Optional[ServiceConnectorInfo] = None,
|
413
|
+
connector_uuid: Optional[UUID] = None,
|
414
|
+
_: AuthContext = Security(authorize),
|
415
|
+
) -> ServiceConnectorResourcesInfo:
|
416
|
+
"""Gets the list of resources that a service connector can access.
|
417
|
+
|
418
|
+
Args:
|
419
|
+
connector_info: The service connector info.
|
420
|
+
connector_uuid: The service connector uuid.
|
421
|
+
|
422
|
+
Returns:
|
423
|
+
The list of resources that the service connector configuration has
|
424
|
+
access to and consumable from UI/CLI.
|
425
|
+
|
426
|
+
Raises:
|
427
|
+
ValueError: If both connector_info and connector_uuid are provided.
|
428
|
+
ValueError: If neither connector_info nor connector_uuid are provided.
|
429
|
+
"""
|
430
|
+
if connector_info is not None and connector_uuid is not None:
|
431
|
+
raise ValueError(
|
432
|
+
"Only one of connector_info or connector_uuid must be provided."
|
433
|
+
)
|
434
|
+
if connector_info is None and connector_uuid is None:
|
435
|
+
raise ValueError(
|
436
|
+
"Either connector_info or connector_uuid must be provided."
|
437
|
+
)
|
438
|
+
|
439
|
+
if connector_info is not None:
|
440
|
+
verify_permission(
|
441
|
+
resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
|
442
|
+
)
|
443
|
+
elif connector_uuid is not None:
|
444
|
+
verify_permission(
|
445
|
+
resource_type=ResourceType.SERVICE_CONNECTOR,
|
446
|
+
action=Action.READ,
|
447
|
+
resource_id=connector_uuid,
|
448
|
+
)
|
449
|
+
|
450
|
+
return get_resources_options_from_resource_model_for_full_stack(
|
451
|
+
connector_details=connector_info or connector_uuid # type: ignore[arg-type]
|
452
|
+
)
|
@@ -117,7 +117,8 @@ def create_run_step(
|
|
117
117
|
pipeline_run = zen_store().get_run(step.pipeline_run_id)
|
118
118
|
verify_permission_for_model(pipeline_run, action=Action.UPDATE)
|
119
119
|
|
120
|
-
|
120
|
+
step_response = zen_store().create_run_step(step_run=step)
|
121
|
+
return dehydrate_response_model(step_response)
|
121
122
|
|
122
123
|
|
123
124
|
@router.get(
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"""Release [0.62.0].
|
2
|
+
|
3
|
+
Revision ID: 0.62.0
|
4
|
+
Revises: b4fca5241eea
|
5
|
+
Create Date: 2024-07-15 14:15:45.347033
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
# revision identifiers, used by Alembic.
|
10
|
+
revision = "0.62.0"
|
11
|
+
down_revision = "b4fca5241eea"
|
12
|
+
branch_labels = None
|
13
|
+
depends_on = None
|
14
|
+
|
15
|
+
|
16
|
+
def upgrade() -> None:
|
17
|
+
"""Upgrade database schema and/or data, creating a new revision."""
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
def downgrade() -> None:
|
22
|
+
"""Downgrade database schema and/or data back to the previous revision."""
|
23
|
+
pass
|
@@ -0,0 +1,167 @@
|
|
1
|
+
"""Migrate onboarding state [b4fca5241eea].
|
2
|
+
|
3
|
+
Revision ID: b4fca5241eea
|
4
|
+
Revises: 0.61.0
|
5
|
+
Create Date: 2024-06-20 15:01:22.414801
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
import json
|
10
|
+
from typing import Dict, List
|
11
|
+
|
12
|
+
import sqlalchemy as sa
|
13
|
+
from alembic import op
|
14
|
+
|
15
|
+
# revision identifiers, used by Alembic.
|
16
|
+
revision = "b4fca5241eea"
|
17
|
+
down_revision = "0.61.0"
|
18
|
+
branch_labels = None
|
19
|
+
depends_on = None
|
20
|
+
|
21
|
+
|
22
|
+
ONBOARDING_KEY_MAPPING = {
|
23
|
+
"connect_zenml": ["device_verified"],
|
24
|
+
"run_first_pipeline": ["pipeline_run", "starter_setup_completed"],
|
25
|
+
"run_remote_pipeline": [
|
26
|
+
"production_setup_completed",
|
27
|
+
],
|
28
|
+
}
|
29
|
+
|
30
|
+
|
31
|
+
def upgrade() -> None:
|
32
|
+
"""Upgrade database schema and/or data, creating a new revision."""
|
33
|
+
connection = op.get_bind()
|
34
|
+
|
35
|
+
meta = sa.MetaData()
|
36
|
+
meta.reflect(only=("server_settings",), bind=connection)
|
37
|
+
|
38
|
+
server_settings_table = sa.Table("server_settings", meta)
|
39
|
+
|
40
|
+
existing_onboarding_state = connection.execute(
|
41
|
+
sa.select(server_settings_table.c.onboarding_state)
|
42
|
+
).scalar_one_or_none()
|
43
|
+
|
44
|
+
new_state = []
|
45
|
+
|
46
|
+
if existing_onboarding_state:
|
47
|
+
# There was already an existing onboarding state in the DB
|
48
|
+
# -> Migrate to the new server keys
|
49
|
+
state = json.loads(existing_onboarding_state)
|
50
|
+
|
51
|
+
if isinstance(state, Dict):
|
52
|
+
for key in state.keys():
|
53
|
+
if key in ONBOARDING_KEY_MAPPING:
|
54
|
+
new_state.extend(ONBOARDING_KEY_MAPPING[key])
|
55
|
+
elif isinstance(state, List):
|
56
|
+
# Somehow the state is already converted, probably shouldn't happen
|
57
|
+
return
|
58
|
+
|
59
|
+
# We now query the DB and complete all onboarding steps that we can detect
|
60
|
+
# from the database
|
61
|
+
meta = sa.MetaData()
|
62
|
+
meta.reflect(
|
63
|
+
only=(
|
64
|
+
"pipeline_run",
|
65
|
+
"stack_component",
|
66
|
+
"stack",
|
67
|
+
"stack_composition",
|
68
|
+
"pipeline_deployment",
|
69
|
+
),
|
70
|
+
bind=connection,
|
71
|
+
)
|
72
|
+
|
73
|
+
pipeline_run_table = sa.Table("pipeline_run", meta)
|
74
|
+
stack_component_table = sa.Table("stack_component", meta)
|
75
|
+
stack_table = sa.Table("stack", meta)
|
76
|
+
stack_composition_table = sa.Table("stack_composition", meta)
|
77
|
+
pipeline_deployment_table = sa.Table("pipeline_deployment", meta)
|
78
|
+
|
79
|
+
pipeline_run_count = connection.execute(
|
80
|
+
sa.select(sa.func.count(pipeline_run_table.c.id))
|
81
|
+
).scalar()
|
82
|
+
if pipeline_run_count and pipeline_run_count > 0:
|
83
|
+
new_state.extend(ONBOARDING_KEY_MAPPING["run_first_pipeline"])
|
84
|
+
|
85
|
+
stack_with_remote_orchestrator_count = connection.execute(
|
86
|
+
sa.select(sa.func.count(stack_table.c.id))
|
87
|
+
.where(stack_composition_table.c.stack_id == stack_table.c.id)
|
88
|
+
.where(
|
89
|
+
stack_composition_table.c.component_id
|
90
|
+
== stack_component_table.c.id
|
91
|
+
)
|
92
|
+
.where(
|
93
|
+
stack_component_table.c.flavor.not_in(["local", "local_docker"])
|
94
|
+
)
|
95
|
+
.where(stack_component_table.c.type == "orchestrator")
|
96
|
+
).scalar()
|
97
|
+
if (
|
98
|
+
stack_with_remote_orchestrator_count
|
99
|
+
and stack_with_remote_orchestrator_count > 0
|
100
|
+
):
|
101
|
+
new_state.append("stack_with_remote_orchestrator_created")
|
102
|
+
|
103
|
+
pipeline_run_with_remote_artifact_store_count = connection.execute(
|
104
|
+
sa.select(sa.func.count(pipeline_run_table.c.id))
|
105
|
+
.where(
|
106
|
+
pipeline_run_table.c.deployment_id
|
107
|
+
== pipeline_deployment_table.c.id
|
108
|
+
)
|
109
|
+
.where(pipeline_deployment_table.c.stack_id == stack_table.c.id)
|
110
|
+
.where(stack_composition_table.c.stack_id == stack_table.c.id)
|
111
|
+
.where(
|
112
|
+
stack_composition_table.c.component_id
|
113
|
+
== stack_component_table.c.id
|
114
|
+
)
|
115
|
+
.where(stack_component_table.c.flavor != "local")
|
116
|
+
.where(stack_component_table.c.type == "artifact_store")
|
117
|
+
).scalar()
|
118
|
+
if (
|
119
|
+
pipeline_run_with_remote_artifact_store_count
|
120
|
+
and pipeline_run_with_remote_artifact_store_count > 0
|
121
|
+
):
|
122
|
+
new_state.append("production_setup_completed")
|
123
|
+
|
124
|
+
pipeline_run_with_remote_orchestrator_count = connection.execute(
|
125
|
+
sa.select(sa.func.count(pipeline_run_table.c.id))
|
126
|
+
.where(
|
127
|
+
pipeline_run_table.c.deployment_id
|
128
|
+
== pipeline_deployment_table.c.id
|
129
|
+
)
|
130
|
+
.where(pipeline_deployment_table.c.stack_id == stack_table.c.id)
|
131
|
+
.where(stack_composition_table.c.stack_id == stack_table.c.id)
|
132
|
+
.where(
|
133
|
+
stack_composition_table.c.component_id
|
134
|
+
== stack_component_table.c.id
|
135
|
+
)
|
136
|
+
.where(
|
137
|
+
stack_component_table.c.flavor.not_in(["local", "local_docker"])
|
138
|
+
)
|
139
|
+
.where(stack_component_table.c.type == "orchestrator")
|
140
|
+
).scalar()
|
141
|
+
if (
|
142
|
+
pipeline_run_with_remote_orchestrator_count
|
143
|
+
and pipeline_run_with_remote_orchestrator_count > 0
|
144
|
+
):
|
145
|
+
new_state.append("pipeline_run_with_remote_orchestrator")
|
146
|
+
new_state.append("production_setup_completed")
|
147
|
+
|
148
|
+
if new_state:
|
149
|
+
# If any of the items are finished, we also complete the initial
|
150
|
+
# onboarding step which is not explicitly tracked in the database
|
151
|
+
new_state.append("device_verified")
|
152
|
+
|
153
|
+
# Remove duplicate keys
|
154
|
+
new_state = list(set(new_state))
|
155
|
+
|
156
|
+
connection.execute(
|
157
|
+
sa.update(server_settings_table).values(
|
158
|
+
onboarding_state=json.dumps(new_state)
|
159
|
+
)
|
160
|
+
)
|
161
|
+
|
162
|
+
|
163
|
+
def downgrade() -> None:
|
164
|
+
"""Downgrade database schema and/or data back to the previous revision."""
|
165
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
166
|
+
pass
|
167
|
+
# ### end Alembic commands ###
|
@@ -2591,6 +2591,10 @@ class RestZenStore(BaseZenStore):
|
|
2591
2591
|
response_body = self.get(
|
2592
2592
|
f"{WORKSPACES}/{workspace_name_or_id}{SERVICE_CONNECTORS}{SERVICE_CONNECTOR_RESOURCES}",
|
2593
2593
|
params=params,
|
2594
|
+
timeout=max(
|
2595
|
+
self.config.http_timeout,
|
2596
|
+
SERVICE_CONNECTOR_VERIFY_REQUEST_TIMEOUT,
|
2597
|
+
),
|
2594
2598
|
)
|
2595
2599
|
|
2596
2600
|
assert isinstance(response_body, list)
|
@@ -38,6 +38,7 @@ from zenml.zen_stores.schemas.user_schemas import UserSchema
|
|
38
38
|
from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
|
39
39
|
|
40
40
|
if TYPE_CHECKING:
|
41
|
+
from zenml.zen_stores.schemas.flavor_schemas import FlavorSchema
|
41
42
|
from zenml.zen_stores.schemas.logs_schemas import LogsSchema
|
42
43
|
from zenml.zen_stores.schemas.run_metadata_schemas import RunMetadataSchema
|
43
44
|
from zenml.zen_stores.schemas.schedule_schema import ScheduleSchema
|
@@ -85,6 +86,13 @@ class StackComponentSchema(NamedSchema, table=True):
|
|
85
86
|
run_metadata: List["RunMetadataSchema"] = Relationship(
|
86
87
|
back_populates="stack_component",
|
87
88
|
)
|
89
|
+
flavor_schema: Optional["FlavorSchema"] = Relationship(
|
90
|
+
sa_relationship_kwargs={
|
91
|
+
"primaryjoin": "and_(foreign(StackComponentSchema.flavor) == FlavorSchema.name, foreign(StackComponentSchema.type) == FlavorSchema.type)",
|
92
|
+
"lazy": "joined",
|
93
|
+
"uselist": False,
|
94
|
+
},
|
95
|
+
)
|
88
96
|
|
89
97
|
run_or_step_logs: List["LogsSchema"] = Relationship(
|
90
98
|
back_populates="artifact_store",
|
@@ -161,6 +169,12 @@ class StackComponentSchema(NamedSchema, table=True):
|
|
161
169
|
user=self.user.to_model() if self.user else None,
|
162
170
|
created=self.created,
|
163
171
|
updated=self.updated,
|
172
|
+
logo_url=self.flavor_schema.logo_url
|
173
|
+
if self.flavor_schema
|
174
|
+
else None,
|
175
|
+
integration=self.flavor_schema.integration
|
176
|
+
if self.flavor_schema
|
177
|
+
else None,
|
164
178
|
)
|
165
179
|
metadata = None
|
166
180
|
if include_metadata:
|
@@ -15,7 +15,7 @@
|
|
15
15
|
|
16
16
|
import json
|
17
17
|
from datetime import datetime
|
18
|
-
from typing import Any, Optional
|
18
|
+
from typing import Any, Optional, Set
|
19
19
|
from uuid import UUID
|
20
20
|
|
21
21
|
from sqlmodel import Field, SQLModel
|
@@ -59,16 +59,33 @@ class ServerSettingsSchema(SQLModel, table=True):
|
|
59
59
|
for field, value in settings_update.model_dump(
|
60
60
|
exclude_unset=True
|
61
61
|
).items():
|
62
|
-
if field
|
63
|
-
if value is not None:
|
64
|
-
self.onboarding_state = json.dumps(value)
|
65
|
-
elif hasattr(self, field):
|
62
|
+
if hasattr(self, field):
|
66
63
|
setattr(self, field, value)
|
67
64
|
|
68
65
|
self.updated = datetime.utcnow()
|
69
66
|
|
70
67
|
return self
|
71
68
|
|
69
|
+
def update_onboarding_state(
|
70
|
+
self, completed_steps: Set[str]
|
71
|
+
) -> "ServerSettingsSchema":
|
72
|
+
"""Update the onboarding state.
|
73
|
+
|
74
|
+
Args:
|
75
|
+
completed_steps: Newly completed onboarding steps.
|
76
|
+
|
77
|
+
Returns:
|
78
|
+
The updated schema.
|
79
|
+
"""
|
80
|
+
old_state = set(
|
81
|
+
json.loads(self.onboarding_state) if self.onboarding_state else []
|
82
|
+
)
|
83
|
+
new_state = old_state.union(completed_steps)
|
84
|
+
self.onboarding_state = json.dumps(list(new_state))
|
85
|
+
self.updated = datetime.utcnow()
|
86
|
+
|
87
|
+
return self
|
88
|
+
|
72
89
|
def to_model(
|
73
90
|
self,
|
74
91
|
include_metadata: bool = False,
|
@@ -82,7 +99,6 @@ class ServerSettingsSchema(SQLModel, table=True):
|
|
82
99
|
include_resources: Whether the resources will be filled.
|
83
100
|
**kwargs: Keyword arguments to allow schema specific logic
|
84
101
|
|
85
|
-
|
86
102
|
Returns:
|
87
103
|
The created `SettingsResponse`.
|
88
104
|
"""
|
@@ -101,11 +117,7 @@ class ServerSettingsSchema(SQLModel, table=True):
|
|
101
117
|
resources = None
|
102
118
|
|
103
119
|
if include_metadata:
|
104
|
-
metadata = ServerSettingsResponseMetadata(
|
105
|
-
onboarding_state=json.loads(self.onboarding_state)
|
106
|
-
if self.onboarding_state
|
107
|
-
else {},
|
108
|
-
)
|
120
|
+
metadata = ServerSettingsResponseMetadata()
|
109
121
|
|
110
122
|
if include_resources:
|
111
123
|
resources = ServerSettingsResponseResources()
|