zenml-nightly 0.62.0.dev20240729__py3-none-any.whl → 0.63.0.dev20240731__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 +1 -1
- RELEASE_NOTES.md +41 -0
- zenml/VERSION +1 -1
- zenml/actions/pipeline_run/pipeline_run_action.py +19 -17
- zenml/analytics/enums.py +4 -0
- zenml/cli/__init__.py +28 -15
- zenml/cli/base.py +1 -1
- zenml/cli/pipeline.py +54 -61
- zenml/cli/stack.py +6 -8
- zenml/client.py +232 -99
- zenml/config/compiler.py +14 -22
- zenml/config/pipeline_run_configuration.py +3 -0
- zenml/config/server_config.py +3 -0
- zenml/config/source.py +2 -1
- zenml/constants.py +2 -0
- zenml/enums.py +3 -0
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +13 -4
- zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +11 -2
- zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +19 -13
- zenml/models/__init__.py +26 -10
- zenml/models/v2/base/filter.py +32 -0
- zenml/models/v2/core/pipeline.py +73 -89
- zenml/models/v2/core/pipeline_build.py +15 -11
- zenml/models/v2/core/pipeline_deployment.py +56 -0
- zenml/models/v2/core/pipeline_run.py +52 -1
- zenml/models/v2/core/run_template.py +393 -0
- zenml/models/v2/misc/stack_deployment.py +5 -0
- zenml/new/pipelines/build_utils.py +34 -58
- zenml/new/pipelines/pipeline.py +17 -76
- zenml/new/pipelines/run_utils.py +12 -0
- zenml/post_execution/pipeline.py +1 -4
- zenml/service_connectors/service_connector_utils.py +4 -2
- zenml/stack_deployments/aws_stack_deployment.py +6 -5
- zenml/stack_deployments/azure_stack_deployment.py +118 -11
- zenml/stack_deployments/gcp_stack_deployment.py +12 -5
- zenml/stack_deployments/stack_deployment.py +6 -5
- zenml/steps/utils.py +0 -4
- zenml/utils/package_utils.py +39 -0
- zenml/zen_server/dashboard/assets/{404-B_YdvmwS.js → 404-CI13wQp4.js} +1 -1
- zenml/zen_server/dashboard/assets/{@reactflow-l_1hUr1S.js → @reactflow-DIYUhKYX.js} +1 -1
- zenml/zen_server/dashboard/assets/{@tanstack-DYiOyJUL.js → @tanstack-k96lU_C-.js} +4 -4
- zenml/zen_server/dashboard/assets/{AwarenessChannel-CFg5iX4Z.js → AwarenessChannel-BNg5uWgI.js} +1 -1
- zenml/zen_server/dashboard/assets/{CodeSnippet-Dvkx_82E.js → CodeSnippet-Cyp7f4dM.js} +2 -2
- zenml/zen_server/dashboard/assets/CollapsibleCard-Cu_A9W57.js +1 -0
- zenml/zen_server/dashboard/assets/{Commands-DoN1xrEq.js → Commands-DmQwTXjj.js} +1 -1
- zenml/zen_server/dashboard/assets/{CopyButton-Cr7xYEPb.js → CopyButton-B3sWVJ4Z.js} +1 -1
- zenml/zen_server/dashboard/assets/{CsvVizualization-Ck-nZ43m.js → CsvVizualization-BvqItd-O.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-kLtljEOM.js → Error-DbXCTGua.js} +1 -1
- zenml/zen_server/dashboard/assets/{ExecutionStatus-DguLLgTK.js → ExecutionStatus-9zM7eaLh.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-BXUMP21n.js → Helpbox-BIiNc-uH.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-DSt0O-dm.js → Infobox-iv1Nu1A0.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-xsrsIGE-.js → InlineAvatar-BvBtO2Dp.js} +1 -1
- zenml/zen_server/dashboard/assets/ProviderRadio-pSAvrGRS.js +1 -0
- zenml/zen_server/dashboard/assets/SearchField-CXoBknpt.js +1 -0
- zenml/zen_server/dashboard/assets/{SetPassword-BXGTWiwj.js → SetPassword-BOxpgh6N.js} +1 -1
- zenml/zen_server/dashboard/assets/{SuccessStep-DZC60t0x.js → SuccessStep-CTSKN2lp.js} +1 -1
- zenml/zen_server/dashboard/assets/Tick-Bnr2TpW6.js +1 -0
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DGvwFWO1.js → UpdatePasswordSchemas-BeCeaRW5.js} +1 -1
- zenml/zen_server/dashboard/assets/chevron-down-D_ZlKMqH.js +1 -0
- zenml/zen_server/dashboard/assets/{cloud-only-C_yFCAkP.js → cloud-only-qelmY92E.js} +1 -1
- zenml/zen_server/dashboard/assets/components-DWe4cTjS.js +1 -0
- zenml/zen_server/dashboard/assets/dots-horizontal-BObFzD5l.js +1 -0
- zenml/zen_server/dashboard/assets/{index-BczVOqUf.js → index-KsTz2dHG.js} +5 -5
- zenml/zen_server/dashboard/assets/index-vfjX_fJV.css +1 -0
- zenml/zen_server/dashboard/assets/index.esm-CbHNSeVw.js +1 -0
- zenml/zen_server/dashboard/assets/{login-mutation-CrHrndTI.js → login-mutation-DRpbESS7.js} +1 -1
- zenml/zen_server/dashboard/assets/{not-found-DYa4pC-C.js → not-found-Dfx9hfkf.js} +1 -1
- zenml/zen_server/dashboard/assets/package-ClbU3KUi.js +1 -0
- zenml/zen_server/dashboard/assets/{page-uA5prJGY.js → page-399pVZHU.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-1h_sD1jz.js → page-BoFtUD9H.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BDns21Iz.js → page-Btu39x7k.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BnaevhnB.js → page-BxiWdeyg.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-1iL8aMqs.js → page-C176KxyB.js} +1 -1
- zenml/zen_server/dashboard/assets/page-C6tXXjnK.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BkeAAYwp.js → page-CDgZmwxP.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CP9obrnG.js +1 -0
- zenml/zen_server/dashboard/assets/{page-C6-UGEbH.js → page-CZe9GEBF.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CaTOsNNw.js +1 -0
- zenml/zen_server/dashboard/assets/{page-CCNRIt_f.js → page-Cjn97HMv.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CmXmB_5i.js +1 -0
- zenml/zen_server/dashboard/assets/page-CvGAOfad.js +1 -0
- zenml/zen_server/dashboard/assets/page-CzucfYPo.js +2 -0
- zenml/zen_server/dashboard/assets/{page-Bi-wtWiO.js → page-D0bbc-qr.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DLEtD2ex.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BhgCDInH.js → page-DVPxY5fT.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BkuQDIf-.js → page-DYBNGxJt.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-8a4UMKXZ.js → page-DtpwnNXq.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-B6h3iaHJ.js → page-DupV0aBd.js} +1 -1
- zenml/zen_server/dashboard/assets/page-EweAR81y.js +1 -0
- zenml/zen_server/dashboard/assets/{page-MFQyIJd3.js → page-f3jBVI5Z.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-2grKx_MY.js → page-p2hLJdS2.js} +1 -1
- zenml/zen_server/dashboard/assets/page-w-YaL77M.js +9 -0
- zenml/zen_server/dashboard/assets/persist-BReKApOc.js +14 -0
- zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +1 -0
- zenml/zen_server/dashboard/assets/{stack-detail-query-Cficsl6d.js → stack-detail-query-Ck7j7BP_.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-7d8xi1tS.js → update-server-settings-mutation-f3ZT7psb.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-D7mAQGUM.js → url-rGEp5Umh.js} +1 -1
- zenml/zen_server/dashboard/assets/{zod-BhoGpZ63.js → zod-BtSyGx4C.js} +1 -1
- zenml/zen_server/dashboard/index.html +5 -5
- 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.12246c7548e71e2c4438e496360de80c.js → precache-manifest.2fa6e528a6e7447caaf35dadfe7514bb.js} +4 -4
- zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
- zenml/zen_server/dashboard_legacy/static/js/{main.3b27024b.chunk.js → main.4aab7e98.chunk.js} +2 -2
- zenml/zen_server/dashboard_legacy/static/js/{main.3b27024b.chunk.js.map → main.4aab7e98.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/models.py +1 -0
- zenml/zen_server/rbac/utils.py +4 -0
- zenml/zen_server/routers/pipeline_builds_endpoints.py +2 -66
- zenml/zen_server/routers/pipeline_deployments_endpoints.py +2 -53
- zenml/zen_server/routers/pipelines_endpoints.py +1 -74
- zenml/zen_server/routers/run_templates_endpoints.py +212 -0
- zenml/zen_server/routers/workspaces_endpoints.py +79 -0
- zenml/zen_server/{pipeline_deployment → template_execution}/runner_entrypoint_configuration.py +1 -8
- zenml/zen_server/{pipeline_deployment → template_execution}/utils.py +214 -92
- zenml/zen_server/utils.py +2 -2
- zenml/zen_server/zen_server_api.py +2 -1
- zenml/zen_stores/migrations/versions/0.63.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/7d1919bb1ef0_add_run_templates.py +100 -0
- zenml/zen_stores/migrations/versions/b59aa68fdb1f_simplify_pipelines.py +139 -0
- zenml/zen_stores/rest_zen_store.py +107 -36
- zenml/zen_stores/schemas/__init__.py +2 -0
- zenml/zen_stores/schemas/pipeline_build_schemas.py +3 -3
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +29 -2
- zenml/zen_stores/schemas/pipeline_run_schemas.py +26 -3
- zenml/zen_stores/schemas/pipeline_schemas.py +29 -30
- zenml/zen_stores/schemas/run_template_schemas.py +264 -0
- zenml/zen_stores/schemas/step_run_schemas.py +11 -4
- zenml/zen_stores/sql_zen_store.py +364 -150
- zenml/zen_stores/template_utils.py +261 -0
- zenml/zen_stores/zen_store_interface.py +93 -20
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.63.0.dev20240731.dist-info}/METADATA +2 -2
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.63.0.dev20240731.dist-info}/RECORD +139 -129
- zenml/models/v2/core/pipeline_namespace.py +0 -113
- zenml/new/pipelines/deserialization_utils.py +0 -292
- zenml/zen_server/dashboard/assets/CollapsibleCard-opiuBHHc.js +0 -1
- zenml/zen_server/dashboard/assets/Pagination-C6X-mifw.js +0 -1
- zenml/zen_server/dashboard/assets/index-EpMIKgrI.css +0 -1
- zenml/zen_server/dashboard/assets/index-rK_Wuy2W.js +0 -1
- zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +0 -1
- zenml/zen_server/dashboard/assets/package-B3fWP-Dh.js +0 -1
- zenml/zen_server/dashboard/assets/page-5NCOHOsy.js +0 -1
- zenml/zen_server/dashboard/assets/page-Bq0YxkLV.js +0 -1
- zenml/zen_server/dashboard/assets/page-Bs2F4eoD.js +0 -2
- zenml/zen_server/dashboard/assets/page-CHNxpz3n.js +0 -1
- zenml/zen_server/dashboard/assets/page-DgorQFqi.js +0 -1
- zenml/zen_server/dashboard/assets/page-K8ebxVIs.js +0 -1
- zenml/zen_server/dashboard/assets/page-TgCF0P_U.js +0 -1
- zenml/zen_server/dashboard/assets/page-ZnCEe-eK.js +0 -9
- zenml/zen_server/dashboard/assets/persist-D7HJNBWx.js +0 -1
- zenml/zen_server/dashboard/assets/plus-C8WOyCzt.js +0 -1
- /zenml/zen_server/{pipeline_deployment → template_execution}/__init__.py +0 -0
- /zenml/zen_server/{pipeline_deployment → template_execution}/workload_manager_interface.py +0 -0
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.63.0.dev20240731.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.63.0.dev20240731.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.63.0.dev20240731.dist-info}/entry_points.txt +0 -0
zenml/zen_server/{pipeline_deployment → template_execution}/runner_entrypoint_configuration.py
RENAMED
@@ -17,15 +17,11 @@ from zenml.client import Client
|
|
17
17
|
from zenml.entrypoints.base_entrypoint_configuration import (
|
18
18
|
BaseEntrypointConfiguration,
|
19
19
|
)
|
20
|
-
from zenml.logger import get_logger
|
21
20
|
from zenml.new.pipelines.run_utils import (
|
22
21
|
deploy_pipeline,
|
23
|
-
get_placeholder_run,
|
24
22
|
prepare_model_versions,
|
25
23
|
)
|
26
24
|
|
27
|
-
logger = get_logger(__name__)
|
28
|
-
|
29
25
|
|
30
26
|
class RunnerEntrypointConfiguration(BaseEntrypointConfiguration):
|
31
27
|
"""Runner entrypoint configuration."""
|
@@ -37,12 +33,9 @@ class RunnerEntrypointConfiguration(BaseEntrypointConfiguration):
|
|
37
33
|
to the entrypoint configuration.
|
38
34
|
"""
|
39
35
|
deployment = self.load_deployment()
|
40
|
-
placeholder_run = get_placeholder_run(deployment_id=deployment.id)
|
41
36
|
|
42
37
|
stack = Client().active_stack
|
43
38
|
assert deployment.stack and stack.id == deployment.stack.id
|
44
39
|
|
45
40
|
prepare_model_versions(deployment=deployment)
|
46
|
-
deploy_pipeline(
|
47
|
-
deployment=deployment, stack=stack, placeholder_run=placeholder_run
|
48
|
-
)
|
41
|
+
deploy_pipeline(deployment=deployment, stack=stack)
|
@@ -3,15 +3,19 @@
|
|
3
3
|
import copy
|
4
4
|
import hashlib
|
5
5
|
import sys
|
6
|
-
from typing import List, Optional, Set, Tuple
|
6
|
+
from typing import Any, Dict, List, Optional, Set, Tuple
|
7
7
|
from uuid import UUID
|
8
8
|
|
9
9
|
from fastapi import BackgroundTasks
|
10
10
|
from packaging import version
|
11
11
|
|
12
|
+
from zenml.analytics.enums import AnalyticsEvent
|
13
|
+
from zenml.analytics.utils import track_handler
|
12
14
|
from zenml.config.base_settings import BaseSettings
|
13
15
|
from zenml.config.pipeline_configurations import PipelineConfiguration
|
14
|
-
from zenml.config.pipeline_run_configuration import
|
16
|
+
from zenml.config.pipeline_run_configuration import (
|
17
|
+
PipelineRunConfiguration,
|
18
|
+
)
|
15
19
|
from zenml.config.step_configurations import Step, StepConfiguration
|
16
20
|
from zenml.constants import (
|
17
21
|
ENV_ZENML_ACTIVE_STACK_ID,
|
@@ -19,6 +23,7 @@ from zenml.constants import (
|
|
19
23
|
)
|
20
24
|
from zenml.enums import ExecutionStatus, StackComponentType, StoreType
|
21
25
|
from zenml.integrations.utils import get_integration_for_module
|
26
|
+
from zenml.logger import get_logger
|
22
27
|
from zenml.models import (
|
23
28
|
CodeReferenceRequest,
|
24
29
|
ComponentResponse,
|
@@ -27,62 +32,80 @@ from zenml.models import (
|
|
27
32
|
PipelineDeploymentResponse,
|
28
33
|
PipelineRunResponse,
|
29
34
|
PipelineRunUpdate,
|
35
|
+
RunTemplateResponse,
|
30
36
|
StackResponse,
|
31
37
|
)
|
38
|
+
from zenml.new.pipelines.build_utils import compute_stack_checksum
|
32
39
|
from zenml.new.pipelines.run_utils import (
|
33
40
|
create_placeholder_run,
|
41
|
+
get_default_run_name,
|
34
42
|
validate_run_config_is_runnable_from_server,
|
35
43
|
validate_stack_is_runnable_from_server,
|
36
44
|
)
|
37
45
|
from zenml.stack.flavor import Flavor
|
38
|
-
from zenml.utils import dict_utils,
|
46
|
+
from zenml.utils import dict_utils, settings_utils
|
39
47
|
from zenml.zen_server.auth import AuthContext
|
40
|
-
from zenml.zen_server.
|
48
|
+
from zenml.zen_server.template_execution.runner_entrypoint_configuration import (
|
41
49
|
RunnerEntrypointConfiguration,
|
42
50
|
)
|
43
51
|
from zenml.zen_server.utils import server_config, workload_manager, zen_store
|
44
52
|
|
53
|
+
logger = get_logger(__name__)
|
54
|
+
|
45
55
|
RUNNER_IMAGE_REPOSITORY = "zenml-runner"
|
46
56
|
|
47
57
|
|
48
|
-
def
|
49
|
-
|
58
|
+
def run_template(
|
59
|
+
template: RunTemplateResponse,
|
50
60
|
auth_context: AuthContext,
|
51
61
|
background_tasks: Optional[BackgroundTasks] = None,
|
52
62
|
run_config: Optional[PipelineRunConfiguration] = None,
|
53
63
|
) -> PipelineRunResponse:
|
54
|
-
"""Run a pipeline from
|
64
|
+
"""Run a pipeline from a template.
|
55
65
|
|
56
66
|
Args:
|
57
|
-
|
67
|
+
template: The template to run.
|
58
68
|
auth_context: Authentication context.
|
59
69
|
background_tasks: Background tasks.
|
60
70
|
run_config: The run configuration.
|
61
71
|
|
62
72
|
Raises:
|
63
|
-
ValueError: If the
|
64
|
-
build.
|
73
|
+
ValueError: If the template can not be run.
|
65
74
|
RuntimeError: If the server URL is not set in the server configuration.
|
66
75
|
|
67
76
|
Returns:
|
68
77
|
ID of the new pipeline run.
|
69
78
|
"""
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
79
|
+
if not template.runnable:
|
80
|
+
raise ValueError(
|
81
|
+
"This template can not be run because its associated deployment, "
|
82
|
+
"stack or build have been deleted."
|
83
|
+
)
|
75
84
|
|
76
|
-
|
77
|
-
|
85
|
+
# Guaranteed by the `runnable` check above
|
86
|
+
build = template.build
|
87
|
+
assert build
|
88
|
+
stack = build.stack
|
89
|
+
assert stack
|
90
|
+
|
91
|
+
if build.stack_checksum and build.stack_checksum != compute_stack_checksum(
|
92
|
+
stack=stack
|
93
|
+
):
|
94
|
+
raise ValueError(
|
95
|
+
f"The stack {stack.name} has been updated since it was used for "
|
96
|
+
"the run that is the base for this template. This means the Docker "
|
97
|
+
"images associated with this template most likely do not contain "
|
98
|
+
"the necessary requirements. Please create a new template from a "
|
99
|
+
"recent run on this stack."
|
100
|
+
)
|
78
101
|
|
79
102
|
validate_stack_is_runnable_from_server(zen_store=zen_store(), stack=stack)
|
80
103
|
if run_config:
|
81
104
|
validate_run_config_is_runnable_from_server(run_config)
|
82
105
|
|
83
|
-
deployment_request =
|
84
|
-
|
85
|
-
|
106
|
+
deployment_request = deployment_request_from_template(
|
107
|
+
template=template,
|
108
|
+
config=run_config or PipelineRunConfiguration(),
|
86
109
|
user_id=auth_context.user.id,
|
87
110
|
)
|
88
111
|
|
@@ -104,7 +127,7 @@ def run_pipeline(
|
|
104
127
|
server_url = server_config().server_url
|
105
128
|
if not server_url:
|
106
129
|
raise RuntimeError(
|
107
|
-
"The server URL is not set in the server configuration"
|
130
|
+
"The server URL is not set in the server configuration."
|
108
131
|
)
|
109
132
|
assert build.zenml_version
|
110
133
|
zenml_version = build.zenml_version
|
@@ -128,66 +151,86 @@ def run_pipeline(
|
|
128
151
|
assert placeholder_run
|
129
152
|
|
130
153
|
def _task() -> None:
|
131
|
-
|
132
|
-
|
133
|
-
|
154
|
+
pypi_requirements, apt_packages = get_requirements_for_stack(
|
155
|
+
stack=stack
|
156
|
+
)
|
157
|
+
|
158
|
+
if build.python_version:
|
159
|
+
version_info = version.parse(build.python_version)
|
160
|
+
python_version = f"{version_info.major}.{version_info.minor}"
|
161
|
+
else:
|
162
|
+
python_version = (
|
163
|
+
f"{sys.version_info.major}.{sys.version_info.minor}"
|
134
164
|
)
|
135
165
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
)
|
166
|
+
dockerfile = generate_dockerfile(
|
167
|
+
pypi_requirements=pypi_requirements,
|
168
|
+
apt_packages=apt_packages,
|
169
|
+
zenml_version=zenml_version,
|
170
|
+
python_version=python_version,
|
171
|
+
)
|
143
172
|
|
144
|
-
|
145
|
-
pypi_requirements=pypi_requirements,
|
146
|
-
apt_packages=apt_packages,
|
147
|
-
zenml_version=zenml_version,
|
148
|
-
python_version=python_version,
|
149
|
-
)
|
173
|
+
image_hash = generate_image_hash(dockerfile=dockerfile)
|
150
174
|
|
151
|
-
|
175
|
+
runner_image = workload_manager().build_and_push_image(
|
176
|
+
workload_id=new_deployment.id,
|
177
|
+
dockerfile=dockerfile,
|
178
|
+
image_name=f"{RUNNER_IMAGE_REPOSITORY}:{image_hash}",
|
179
|
+
sync=True,
|
180
|
+
)
|
152
181
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
182
|
+
workload_manager().log(
|
183
|
+
workload_id=new_deployment.id,
|
184
|
+
message="Starting pipeline run.",
|
185
|
+
)
|
186
|
+
workload_manager().run(
|
187
|
+
workload_id=new_deployment.id,
|
188
|
+
image=runner_image,
|
189
|
+
command=command,
|
190
|
+
arguments=args,
|
191
|
+
environment=environment,
|
192
|
+
timeout_in_seconds=30,
|
193
|
+
sync=True,
|
194
|
+
)
|
195
|
+
workload_manager().log(
|
196
|
+
workload_id=new_deployment.id,
|
197
|
+
message="Pipeline run started successfully.",
|
198
|
+
)
|
159
199
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
arguments=args,
|
169
|
-
environment=environment,
|
170
|
-
timeout_in_seconds=30,
|
171
|
-
sync=True,
|
172
|
-
)
|
173
|
-
workload_manager().log(
|
174
|
-
workload_id=new_deployment.id,
|
175
|
-
message="Pipeline deployed successfully.",
|
176
|
-
)
|
177
|
-
except Exception:
|
178
|
-
zen_store().update_run(
|
200
|
+
def _task_with_analytics_and_error_handling() -> None:
|
201
|
+
with track_handler(
|
202
|
+
event=AnalyticsEvent.RUN_PIPELINE
|
203
|
+
) as analytics_handler:
|
204
|
+
analytics_handler.metadata = get_pipeline_run_analytics_metadata(
|
205
|
+
deployment=new_deployment,
|
206
|
+
stack=stack,
|
207
|
+
template_id=template.id,
|
179
208
|
run_id=placeholder_run.id,
|
180
|
-
run_update=PipelineRunUpdate(status=ExecutionStatus.FAILED),
|
181
209
|
)
|
182
|
-
|
210
|
+
|
211
|
+
try:
|
212
|
+
_task()
|
213
|
+
except Exception:
|
214
|
+
logger.exception(
|
215
|
+
"Failed to run template %s, run ID: %s",
|
216
|
+
str(template.id),
|
217
|
+
str(placeholder_run.id),
|
218
|
+
)
|
219
|
+
zen_store().update_run(
|
220
|
+
run_id=placeholder_run.id,
|
221
|
+
run_update=PipelineRunUpdate(
|
222
|
+
status=ExecutionStatus.FAILED
|
223
|
+
),
|
224
|
+
)
|
225
|
+
raise
|
183
226
|
|
184
227
|
if background_tasks:
|
185
|
-
background_tasks.add_task(
|
228
|
+
background_tasks.add_task(_task_with_analytics_and_error_handling)
|
186
229
|
else:
|
187
230
|
# Run synchronously if no background tasks were passed. This is probably
|
188
231
|
# when coming from a trigger which itself is already running in the
|
189
232
|
# background
|
190
|
-
|
233
|
+
_task_with_analytics_and_error_handling()
|
191
234
|
|
192
235
|
return placeholder_run
|
193
236
|
|
@@ -332,47 +375,77 @@ def generate_dockerfile(
|
|
332
375
|
return "\n".join(lines)
|
333
376
|
|
334
377
|
|
335
|
-
def
|
336
|
-
|
337
|
-
|
378
|
+
def deployment_request_from_template(
|
379
|
+
template: RunTemplateResponse,
|
380
|
+
config: PipelineRunConfiguration,
|
338
381
|
user_id: UUID,
|
339
382
|
) -> "PipelineDeploymentRequest":
|
340
|
-
"""
|
383
|
+
"""Generate a deployment request from a template.
|
341
384
|
|
342
385
|
Args:
|
343
|
-
|
344
|
-
|
345
|
-
user_id:
|
386
|
+
template: The template from which to create the deployment request.
|
387
|
+
config: The run configuration.
|
388
|
+
user_id: ID of the user that is trying to run the template.
|
389
|
+
|
390
|
+
Raises:
|
391
|
+
ValueError: If the run configuration is missing step parameters.
|
346
392
|
|
347
393
|
Returns:
|
348
|
-
The
|
394
|
+
The generated deployment request.
|
349
395
|
"""
|
350
|
-
|
351
|
-
|
396
|
+
deployment = template.source_deployment
|
397
|
+
assert deployment
|
398
|
+
pipeline_configuration = PipelineConfiguration(
|
399
|
+
**config.model_dump(
|
400
|
+
include=set(PipelineConfiguration.model_fields),
|
401
|
+
exclude={"name", "parameters"},
|
402
|
+
),
|
403
|
+
name=deployment.pipeline_configuration.name,
|
404
|
+
parameters=deployment.pipeline_configuration.parameters,
|
352
405
|
)
|
353
406
|
|
354
|
-
|
355
|
-
|
356
|
-
)
|
357
|
-
pipeline_configuration_dict = pipeline_configuration.model_dump(
|
358
|
-
exclude_none=True
|
407
|
+
step_config_dict_base = pipeline_configuration.model_dump(
|
408
|
+
exclude={"name", "parameters"}
|
359
409
|
)
|
360
410
|
steps = {}
|
361
411
|
for invocation_id, step in deployment.step_configurations.items():
|
362
|
-
step_config_dict =
|
363
|
-
copy.deepcopy(
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
412
|
+
step_config_dict = {
|
413
|
+
**copy.deepcopy(step_config_dict_base),
|
414
|
+
**step.config.model_dump(
|
415
|
+
# TODO: Maybe we need to make some of these configurable via
|
416
|
+
# yaml as well, e.g. the lazy loaders?
|
417
|
+
include={
|
418
|
+
"name",
|
419
|
+
"caching_parameters",
|
420
|
+
"external_input_artifacts",
|
421
|
+
"model_artifacts_or_metadata",
|
422
|
+
"client_lazy_loaders",
|
423
|
+
"outputs",
|
424
|
+
}
|
425
|
+
),
|
426
|
+
}
|
427
|
+
|
428
|
+
required_parameters = set(step.config.parameters)
|
429
|
+
configured_parameters = set()
|
430
|
+
|
431
|
+
if update := config.steps.get(invocation_id):
|
369
432
|
update_dict = update.model_dump()
|
370
433
|
# Get rid of deprecated name to prevent overriding the step name
|
371
434
|
# with `None`.
|
372
435
|
update_dict.pop("name", None)
|
373
|
-
|
374
|
-
|
436
|
+
configured_parameters = set(update.parameters)
|
437
|
+
step_config_dict = dict_utils.recursive_update(
|
438
|
+
step_config_dict, update=update_dict
|
375
439
|
)
|
440
|
+
|
441
|
+
if configured_parameters != required_parameters:
|
442
|
+
missing_parameters = required_parameters - configured_parameters
|
443
|
+
raise ValueError(
|
444
|
+
"Run configuration is missing missing the following required "
|
445
|
+
f"parameters for step {step.config.name}: {missing_parameters}."
|
446
|
+
)
|
447
|
+
|
448
|
+
step_config = StepConfiguration.model_validate(step_config_dict)
|
376
449
|
steps[invocation_id] = Step(spec=step.spec, config=step_config)
|
377
450
|
|
378
451
|
code_reference_request = None
|
@@ -389,7 +462,8 @@ def apply_run_config(
|
|
389
462
|
deployment_request = PipelineDeploymentRequest(
|
390
463
|
user=user_id,
|
391
464
|
workspace=deployment.workspace.id,
|
392
|
-
run_name_template=
|
465
|
+
run_name_template=config.run_name
|
466
|
+
or get_default_run_name(pipeline_name=pipeline_configuration.name),
|
393
467
|
pipeline_configuration=pipeline_configuration,
|
394
468
|
step_configurations=steps,
|
395
469
|
client_environment={},
|
@@ -400,6 +474,54 @@ def apply_run_config(
|
|
400
474
|
build=deployment.build.id,
|
401
475
|
schedule=None,
|
402
476
|
code_reference=code_reference_request,
|
477
|
+
template=template.id,
|
478
|
+
pipeline_version_hash=deployment.pipeline_version_hash,
|
479
|
+
pipeline_spec=deployment.pipeline_spec,
|
403
480
|
)
|
404
481
|
|
405
482
|
return deployment_request
|
483
|
+
|
484
|
+
|
485
|
+
def get_pipeline_run_analytics_metadata(
|
486
|
+
deployment: "PipelineDeploymentResponse",
|
487
|
+
stack: StackResponse,
|
488
|
+
template_id: UUID,
|
489
|
+
run_id: UUID,
|
490
|
+
) -> Dict[str, Any]:
|
491
|
+
"""Get metadata for the pipeline run analytics event.
|
492
|
+
|
493
|
+
Args:
|
494
|
+
deployment: The deployment of the run.
|
495
|
+
stack: The stack on which the run will happen.
|
496
|
+
template_id: ID of the template from which the run was started.
|
497
|
+
run_id: ID of the run.
|
498
|
+
|
499
|
+
Returns:
|
500
|
+
The analytics metadata.
|
501
|
+
"""
|
502
|
+
custom_materializer = False
|
503
|
+
for step in deployment.step_configurations.values():
|
504
|
+
for output in step.config.outputs.values():
|
505
|
+
for source in output.materializer_source:
|
506
|
+
if not source.is_internal:
|
507
|
+
custom_materializer = True
|
508
|
+
|
509
|
+
assert deployment.user
|
510
|
+
stack_creator = stack.user
|
511
|
+
own_stack = stack_creator and stack_creator.id == deployment.user.id
|
512
|
+
|
513
|
+
stack_metadata = {
|
514
|
+
component_type.value: component_list[0].flavor
|
515
|
+
for component_type, component_list in stack.components.items()
|
516
|
+
}
|
517
|
+
|
518
|
+
return {
|
519
|
+
"store_type": "rest", # This method is called from within a REST endpoint
|
520
|
+
**stack_metadata,
|
521
|
+
"total_steps": len(deployment.step_configurations),
|
522
|
+
"schedule": deployment.schedule is not None,
|
523
|
+
"custom_materializer": custom_materializer,
|
524
|
+
"own_stack": own_stack,
|
525
|
+
"pipeline_run_id": str(run_id),
|
526
|
+
"template_id": str(template_id),
|
527
|
+
}
|
zenml/zen_server/utils.py
CHANGED
@@ -47,10 +47,10 @@ from zenml.zen_server.exceptions import http_exception_from_error
|
|
47
47
|
from zenml.zen_server.feature_gate.feature_gate_interface import (
|
48
48
|
FeatureGateInterface,
|
49
49
|
)
|
50
|
-
from zenml.zen_server.
|
50
|
+
from zenml.zen_server.rbac.rbac_interface import RBACInterface
|
51
|
+
from zenml.zen_server.template_execution.workload_manager_interface import (
|
51
52
|
WorkloadManagerInterface,
|
52
53
|
)
|
53
|
-
from zenml.zen_server.rbac.rbac_interface import RBACInterface
|
54
54
|
from zenml.zen_stores.sql_zen_store import SqlZenStore
|
55
55
|
|
56
56
|
logger = get_logger(__name__)
|
@@ -55,6 +55,7 @@ from zenml.zen_server.routers import (
|
|
55
55
|
pipelines_endpoints,
|
56
56
|
plugin_endpoints,
|
57
57
|
run_metadata_endpoints,
|
58
|
+
run_templates_endpoints,
|
58
59
|
runs_endpoints,
|
59
60
|
schedule_endpoints,
|
60
61
|
secrets_endpoints,
|
@@ -278,11 +279,11 @@ app.include_router(model_versions_endpoints.router)
|
|
278
279
|
app.include_router(model_versions_endpoints.model_version_artifacts_router)
|
279
280
|
app.include_router(model_versions_endpoints.model_version_pipeline_runs_router)
|
280
281
|
app.include_router(pipelines_endpoints.router)
|
281
|
-
app.include_router(pipelines_endpoints.namespace_router)
|
282
282
|
app.include_router(pipeline_builds_endpoints.router)
|
283
283
|
app.include_router(pipeline_deployments_endpoints.router)
|
284
284
|
app.include_router(runs_endpoints.router)
|
285
285
|
app.include_router(run_metadata_endpoints.router)
|
286
|
+
app.include_router(run_templates_endpoints.router)
|
286
287
|
app.include_router(schedule_endpoints.router)
|
287
288
|
app.include_router(secrets_endpoints.router)
|
288
289
|
app.include_router(secrets_endpoints.op_router)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"""Release [0.63.0].
|
2
|
+
|
3
|
+
Revision ID: 0.63.0
|
4
|
+
Revises: 7d1919bb1ef0
|
5
|
+
Create Date: 2024-07-29 16:59:59.891939
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
# revision identifiers, used by Alembic.
|
10
|
+
revision = "0.63.0"
|
11
|
+
down_revision = "7d1919bb1ef0"
|
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,100 @@
|
|
1
|
+
"""Add run templates [7d1919bb1ef0].
|
2
|
+
|
3
|
+
Revision ID: 7d1919bb1ef0
|
4
|
+
Revises: b59aa68fdb1f
|
5
|
+
Create Date: 2024-07-22 11:20:00.544451
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
import sqlalchemy as sa
|
10
|
+
import sqlmodel
|
11
|
+
from alembic import op
|
12
|
+
from sqlalchemy.dialects import mysql
|
13
|
+
|
14
|
+
# revision identifiers, used by Alembic.
|
15
|
+
revision = "7d1919bb1ef0"
|
16
|
+
down_revision = "b59aa68fdb1f"
|
17
|
+
branch_labels = None
|
18
|
+
depends_on = None
|
19
|
+
|
20
|
+
|
21
|
+
def upgrade() -> None:
|
22
|
+
"""Upgrade database schema and/or data, creating a new revision."""
|
23
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
24
|
+
op.create_table(
|
25
|
+
"run_template",
|
26
|
+
sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
|
27
|
+
sa.Column("created", sa.DateTime(), nullable=False),
|
28
|
+
sa.Column("updated", sa.DateTime(), nullable=False),
|
29
|
+
sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
30
|
+
sa.Column(
|
31
|
+
"description",
|
32
|
+
sa.String(length=16777215).with_variant(mysql.MEDIUMTEXT, "mysql"),
|
33
|
+
nullable=True,
|
34
|
+
),
|
35
|
+
sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True),
|
36
|
+
sa.Column(
|
37
|
+
"workspace_id", sqlmodel.sql.sqltypes.GUID(), nullable=False
|
38
|
+
),
|
39
|
+
sa.Column(
|
40
|
+
"source_deployment_id", sqlmodel.sql.sqltypes.GUID(), nullable=True
|
41
|
+
),
|
42
|
+
sa.ForeignKeyConstraint(
|
43
|
+
["source_deployment_id"],
|
44
|
+
["pipeline_deployment.id"],
|
45
|
+
name="fk_run_template_source_deployment_id_pipeline_deployment",
|
46
|
+
ondelete="SET NULL",
|
47
|
+
),
|
48
|
+
sa.ForeignKeyConstraint(
|
49
|
+
["user_id"],
|
50
|
+
["user.id"],
|
51
|
+
name="fk_run_template_user_id_user",
|
52
|
+
ondelete="SET NULL",
|
53
|
+
),
|
54
|
+
sa.ForeignKeyConstraint(
|
55
|
+
["workspace_id"],
|
56
|
+
["workspace.id"],
|
57
|
+
name="fk_run_template_workspace_id_workspace",
|
58
|
+
ondelete="CASCADE",
|
59
|
+
),
|
60
|
+
sa.PrimaryKeyConstraint("id"),
|
61
|
+
sa.UniqueConstraint(
|
62
|
+
"name", "workspace_id", name="unique_template_name_in_workspace"
|
63
|
+
),
|
64
|
+
)
|
65
|
+
with op.batch_alter_table("pipeline_build", schema=None) as batch_op:
|
66
|
+
batch_op.add_column(
|
67
|
+
sa.Column(
|
68
|
+
"stack_checksum",
|
69
|
+
sqlmodel.sql.sqltypes.AutoString(),
|
70
|
+
nullable=True,
|
71
|
+
)
|
72
|
+
)
|
73
|
+
batch_op.drop_column("template_deployment_id")
|
74
|
+
|
75
|
+
with op.batch_alter_table("pipeline_deployment", schema=None) as batch_op:
|
76
|
+
batch_op.add_column(
|
77
|
+
sa.Column(
|
78
|
+
"template_id", sqlmodel.sql.sqltypes.GUID(), nullable=True
|
79
|
+
)
|
80
|
+
)
|
81
|
+
|
82
|
+
# ### end Alembic commands ###
|
83
|
+
|
84
|
+
|
85
|
+
def downgrade() -> None:
|
86
|
+
"""Downgrade database schema and/or data back to the previous revision."""
|
87
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
88
|
+
with op.batch_alter_table("pipeline_deployment", schema=None) as batch_op:
|
89
|
+
batch_op.drop_column("template_id")
|
90
|
+
|
91
|
+
with op.batch_alter_table("pipeline_build", schema=None) as batch_op:
|
92
|
+
batch_op.add_column(
|
93
|
+
sa.Column(
|
94
|
+
"template_deployment_id", sa.CHAR(length=32), nullable=True
|
95
|
+
)
|
96
|
+
)
|
97
|
+
batch_op.drop_column("stack_checksum")
|
98
|
+
|
99
|
+
op.drop_table("run_template")
|
100
|
+
# ### end Alembic commands ###
|