zenml-nightly 0.62.0.dev20240729__py3-none-any.whl → 0.62.0.dev20240730__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 (69) hide show
  1. zenml/VERSION +1 -1
  2. zenml/actions/pipeline_run/pipeline_run_action.py +19 -17
  3. zenml/analytics/enums.py +4 -0
  4. zenml/cli/__init__.py +28 -15
  5. zenml/cli/base.py +1 -1
  6. zenml/cli/pipeline.py +54 -61
  7. zenml/cli/stack.py +6 -8
  8. zenml/client.py +232 -99
  9. zenml/config/compiler.py +14 -22
  10. zenml/config/pipeline_run_configuration.py +3 -0
  11. zenml/config/server_config.py +3 -0
  12. zenml/config/source.py +2 -1
  13. zenml/constants.py +2 -0
  14. zenml/enums.py +3 -0
  15. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +13 -4
  16. zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +11 -2
  17. zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +19 -13
  18. zenml/models/__init__.py +26 -10
  19. zenml/models/v2/base/filter.py +32 -0
  20. zenml/models/v2/core/pipeline.py +73 -89
  21. zenml/models/v2/core/pipeline_build.py +15 -11
  22. zenml/models/v2/core/pipeline_deployment.py +56 -0
  23. zenml/models/v2/core/pipeline_run.py +52 -1
  24. zenml/models/v2/core/run_template.py +393 -0
  25. zenml/models/v2/misc/stack_deployment.py +5 -0
  26. zenml/new/pipelines/build_utils.py +34 -58
  27. zenml/new/pipelines/pipeline.py +17 -76
  28. zenml/new/pipelines/run_utils.py +12 -0
  29. zenml/post_execution/pipeline.py +1 -4
  30. zenml/service_connectors/service_connector_utils.py +4 -2
  31. zenml/stack_deployments/aws_stack_deployment.py +6 -5
  32. zenml/stack_deployments/azure_stack_deployment.py +118 -11
  33. zenml/stack_deployments/gcp_stack_deployment.py +12 -5
  34. zenml/stack_deployments/stack_deployment.py +6 -5
  35. zenml/steps/utils.py +0 -4
  36. zenml/utils/package_utils.py +39 -0
  37. zenml/zen_server/rbac/models.py +1 -0
  38. zenml/zen_server/rbac/utils.py +4 -0
  39. zenml/zen_server/routers/pipeline_builds_endpoints.py +2 -66
  40. zenml/zen_server/routers/pipeline_deployments_endpoints.py +2 -53
  41. zenml/zen_server/routers/pipelines_endpoints.py +1 -74
  42. zenml/zen_server/routers/run_templates_endpoints.py +212 -0
  43. zenml/zen_server/routers/workspaces_endpoints.py +79 -0
  44. zenml/zen_server/{pipeline_deployment → template_execution}/runner_entrypoint_configuration.py +1 -8
  45. zenml/zen_server/{pipeline_deployment → template_execution}/utils.py +214 -92
  46. zenml/zen_server/utils.py +2 -2
  47. zenml/zen_server/zen_server_api.py +2 -1
  48. zenml/zen_stores/migrations/versions/7d1919bb1ef0_add_run_templates.py +100 -0
  49. zenml/zen_stores/migrations/versions/b59aa68fdb1f_simplify_pipelines.py +139 -0
  50. zenml/zen_stores/rest_zen_store.py +107 -36
  51. zenml/zen_stores/schemas/__init__.py +2 -0
  52. zenml/zen_stores/schemas/pipeline_build_schemas.py +3 -3
  53. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +29 -2
  54. zenml/zen_stores/schemas/pipeline_run_schemas.py +26 -3
  55. zenml/zen_stores/schemas/pipeline_schemas.py +29 -30
  56. zenml/zen_stores/schemas/run_template_schemas.py +264 -0
  57. zenml/zen_stores/schemas/step_run_schemas.py +11 -4
  58. zenml/zen_stores/sql_zen_store.py +364 -150
  59. zenml/zen_stores/template_utils.py +261 -0
  60. zenml/zen_stores/zen_store_interface.py +93 -20
  61. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.62.0.dev20240730.dist-info}/METADATA +1 -1
  62. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.62.0.dev20240730.dist-info}/RECORD +67 -63
  63. zenml/models/v2/core/pipeline_namespace.py +0 -113
  64. zenml/new/pipelines/deserialization_utils.py +0 -292
  65. /zenml/zen_server/{pipeline_deployment → template_execution}/__init__.py +0 -0
  66. /zenml/zen_server/{pipeline_deployment → template_execution}/workload_manager_interface.py +0 -0
  67. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.62.0.dev20240730.dist-info}/LICENSE +0 -0
  68. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.62.0.dev20240730.dist-info}/WHEEL +0 -0
  69. {zenml_nightly-0.62.0.dev20240729.dist-info → zenml_nightly-0.62.0.dev20240730.dist-info}/entry_points.txt +0 -0
@@ -13,22 +13,20 @@
13
13
  # permissions and limitations under the License.
14
14
  """SQL Model Implementations for Pipelines and Pipeline Runs."""
15
15
 
16
- import json
17
16
  from datetime import datetime
18
17
  from typing import TYPE_CHECKING, Any, List, Optional
19
18
  from uuid import UUID
20
19
 
21
- from sqlalchemy import TEXT, Column, String
22
- from sqlalchemy.dialects.mysql import MEDIUMTEXT
20
+ from sqlalchemy import TEXT, Column
23
21
  from sqlmodel import Field, Relationship
24
22
 
25
- from zenml.config.pipeline_spec import PipelineSpec
26
- from zenml.constants import MEDIUMTEXT_MAX_LENGTH
23
+ from zenml.enums import TaggableResourceTypes
27
24
  from zenml.models import (
28
25
  PipelineRequest,
29
26
  PipelineResponse,
30
27
  PipelineResponseBody,
31
28
  PipelineResponseMetadata,
29
+ PipelineResponseResources,
32
30
  PipelineUpdate,
33
31
  )
34
32
  from zenml.zen_stores.schemas.base_schemas import NamedSchema
@@ -45,6 +43,7 @@ if TYPE_CHECKING:
45
43
  )
46
44
  from zenml.zen_stores.schemas.pipeline_run_schemas import PipelineRunSchema
47
45
  from zenml.zen_stores.schemas.schedule_schema import ScheduleSchema
46
+ from zenml.zen_stores.schemas.tag_schemas import TagResourceSchema
48
47
 
49
48
 
50
49
  class PipelineSchema(NamedSchema, table=True):
@@ -53,17 +52,7 @@ class PipelineSchema(NamedSchema, table=True):
53
52
  __tablename__ = "pipeline"
54
53
 
55
54
  # Fields
56
- version: str
57
- version_hash: str
58
- docstring: Optional[str] = Field(sa_column=Column(TEXT, nullable=True))
59
- spec: str = Field(
60
- sa_column=Column(
61
- String(length=MEDIUMTEXT_MAX_LENGTH).with_variant(
62
- MEDIUMTEXT, "mysql"
63
- ),
64
- nullable=False,
65
- )
66
- )
55
+ description: Optional[str] = Field(sa_column=Column(TEXT, nullable=True))
67
56
 
68
57
  # Foreign keys
69
58
  workspace_id: UUID = build_foreign_key_field(
@@ -90,13 +79,23 @@ class PipelineSchema(NamedSchema, table=True):
90
79
  schedules: List["ScheduleSchema"] = Relationship(
91
80
  back_populates="pipeline",
92
81
  )
93
- runs: List["PipelineRunSchema"] = Relationship(back_populates="pipeline")
82
+ runs: List["PipelineRunSchema"] = Relationship(
83
+ back_populates="pipeline",
84
+ sa_relationship_kwargs={"order_by": "PipelineRunSchema.created"},
85
+ )
94
86
  builds: List["PipelineBuildSchema"] = Relationship(
95
87
  back_populates="pipeline"
96
88
  )
97
89
  deployments: List["PipelineDeploymentSchema"] = Relationship(
98
90
  back_populates="pipeline",
99
91
  )
92
+ tags: List["TagResourceSchema"] = Relationship(
93
+ sa_relationship_kwargs=dict(
94
+ primaryjoin=f"and_(TagResourceSchema.resource_type=='{TaggableResourceTypes.PIPELINE.value}', foreign(TagResourceSchema.resource_id)==PipelineSchema.id)",
95
+ cascade="delete",
96
+ overlaps="tags",
97
+ ),
98
+ )
100
99
 
101
100
  @classmethod
102
101
  def from_request(
@@ -113,21 +112,15 @@ class PipelineSchema(NamedSchema, table=True):
113
112
  """
114
113
  return cls(
115
114
  name=pipeline_request.name,
116
- version=pipeline_request.version,
117
- version_hash=pipeline_request.version_hash,
115
+ description=pipeline_request.description,
118
116
  workspace_id=pipeline_request.workspace,
119
117
  user_id=pipeline_request.user,
120
- docstring=pipeline_request.docstring,
121
- spec=json.dumps(
122
- pipeline_request.spec.model_dump(mode="json"), sort_keys=True
123
- ),
124
118
  )
125
119
 
126
120
  def to_model(
127
121
  self,
128
122
  include_metadata: bool = False,
129
123
  include_resources: bool = False,
130
- last_x_runs: int = 3,
131
124
  **kwargs: Any,
132
125
  ) -> "PipelineResponse":
133
126
  """Convert a `PipelineSchema` to a `PipelineResponse`.
@@ -136,25 +129,29 @@ class PipelineSchema(NamedSchema, table=True):
136
129
  include_metadata: Whether the metadata will be filled.
137
130
  include_resources: Whether the resources will be filled.
138
131
  **kwargs: Keyword arguments to allow schema specific logic
139
- last_x_runs: How many runs to use for the execution status
140
132
 
141
133
  Returns:
142
134
  The created PipelineResponse.
143
135
  """
144
136
  body = PipelineResponseBody(
145
137
  user=self.user.to_model() if self.user else None,
146
- status=[run.status for run in self.runs[:last_x_runs]],
138
+ latest_run_id=self.runs[-1].id if self.runs else None,
139
+ latest_run_status=self.runs[-1].status if self.runs else None,
147
140
  created=self.created,
148
141
  updated=self.updated,
149
- version=self.version,
150
142
  )
143
+
151
144
  metadata = None
152
145
  if include_metadata:
153
146
  metadata = PipelineResponseMetadata(
154
147
  workspace=self.workspace.to_model(),
155
- version_hash=self.version_hash,
156
- spec=PipelineSpec.model_validate_json(self.spec),
157
- docstring=self.docstring,
148
+ description=self.description,
149
+ )
150
+
151
+ resources = None
152
+ if include_resources:
153
+ resources = PipelineResponseResources(
154
+ tags=[t.tag.to_model() for t in self.tags],
158
155
  )
159
156
 
160
157
  return PipelineResponse(
@@ -162,6 +159,7 @@ class PipelineSchema(NamedSchema, table=True):
162
159
  name=self.name,
163
160
  body=body,
164
161
  metadata=metadata,
162
+ resources=resources,
165
163
  )
166
164
 
167
165
  def update(self, pipeline_update: "PipelineUpdate") -> "PipelineSchema":
@@ -173,5 +171,6 @@ class PipelineSchema(NamedSchema, table=True):
173
171
  Returns:
174
172
  The updated `PipelineSchema`.
175
173
  """
174
+ self.description = pipeline_update.description
176
175
  self.updated = datetime.utcnow()
177
176
  return self
@@ -0,0 +1,264 @@
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
+ """SQLModel implementation of run template tables."""
15
+
16
+ from datetime import datetime
17
+ from typing import TYPE_CHECKING, Any, List, Optional
18
+ from uuid import UUID
19
+
20
+ from sqlalchemy import Column, String, UniqueConstraint
21
+ from sqlalchemy.dialects.mysql import MEDIUMTEXT
22
+ from sqlmodel import Field, Relationship
23
+
24
+ from zenml.constants import MEDIUMTEXT_MAX_LENGTH
25
+ from zenml.enums import TaggableResourceTypes
26
+ from zenml.models import (
27
+ RunTemplateRequest,
28
+ RunTemplateResponse,
29
+ RunTemplateResponseBody,
30
+ RunTemplateResponseMetadata,
31
+ RunTemplateResponseResources,
32
+ RunTemplateUpdate,
33
+ )
34
+ from zenml.zen_stores.schemas.base_schemas import BaseSchema
35
+ from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
36
+ from zenml.zen_stores.schemas.user_schemas import UserSchema
37
+ from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
38
+
39
+ if TYPE_CHECKING:
40
+ from zenml.zen_stores.schemas.pipeline_deployment_schemas import (
41
+ PipelineDeploymentSchema,
42
+ )
43
+ from zenml.zen_stores.schemas.pipeline_run_schemas import PipelineRunSchema
44
+ from zenml.zen_stores.schemas.tag_schemas import TagResourceSchema
45
+
46
+
47
+ class RunTemplateSchema(BaseSchema, table=True):
48
+ """SQL Model for run templates."""
49
+
50
+ __tablename__ = "run_template"
51
+ __table_args__ = (
52
+ UniqueConstraint(
53
+ "name",
54
+ "workspace_id",
55
+ name="unique_template_name_in_workspace",
56
+ ),
57
+ )
58
+
59
+ name: str = Field(nullable=False)
60
+ description: Optional[str] = Field(
61
+ sa_column=Column(
62
+ String(length=MEDIUMTEXT_MAX_LENGTH).with_variant(
63
+ MEDIUMTEXT, "mysql"
64
+ ),
65
+ nullable=True,
66
+ )
67
+ )
68
+
69
+ user_id: Optional[UUID] = build_foreign_key_field(
70
+ source=__tablename__,
71
+ target=UserSchema.__tablename__,
72
+ source_column="user_id",
73
+ target_column="id",
74
+ ondelete="SET NULL",
75
+ nullable=True,
76
+ )
77
+ workspace_id: UUID = build_foreign_key_field(
78
+ source=__tablename__,
79
+ target=WorkspaceSchema.__tablename__,
80
+ source_column="workspace_id",
81
+ target_column="id",
82
+ ondelete="CASCADE",
83
+ nullable=False,
84
+ )
85
+ source_deployment_id: Optional[UUID] = build_foreign_key_field(
86
+ source=__tablename__,
87
+ target="pipeline_deployment",
88
+ source_column="source_deployment_id",
89
+ target_column="id",
90
+ ondelete="SET NULL",
91
+ nullable=True,
92
+ )
93
+
94
+ user: Optional["UserSchema"] = Relationship()
95
+ workspace: "WorkspaceSchema" = Relationship()
96
+ source_deployment: Optional["PipelineDeploymentSchema"] = Relationship(
97
+ sa_relationship_kwargs={
98
+ "foreign_keys": "RunTemplateSchema.source_deployment_id",
99
+ }
100
+ )
101
+
102
+ runs: List["PipelineRunSchema"] = Relationship(
103
+ sa_relationship_kwargs={
104
+ "primaryjoin": "RunTemplateSchema.id==PipelineDeploymentSchema.template_id",
105
+ "secondaryjoin": "PipelineDeploymentSchema.id==PipelineRunSchema.deployment_id",
106
+ "secondary": "pipeline_deployment",
107
+ "cascade": "delete",
108
+ "viewonly": True,
109
+ "order_by": "PipelineRunSchema.created",
110
+ }
111
+ )
112
+
113
+ tags: List["TagResourceSchema"] = Relationship(
114
+ sa_relationship_kwargs=dict(
115
+ primaryjoin=f"and_(TagResourceSchema.resource_type=='{TaggableResourceTypes.RUN_TEMPLATE.value}', foreign(TagResourceSchema.resource_id)==RunTemplateSchema.id)",
116
+ cascade="delete",
117
+ overlaps="tags",
118
+ ),
119
+ )
120
+
121
+ @classmethod
122
+ def from_request(
123
+ cls,
124
+ request: RunTemplateRequest,
125
+ ) -> "RunTemplateSchema":
126
+ """Create a schema from a request.
127
+
128
+ Args:
129
+ request: The request to convert.
130
+
131
+
132
+ Returns:
133
+ The created schema.
134
+ """
135
+ return cls(
136
+ user_id=request.user,
137
+ workspace_id=request.workspace,
138
+ name=request.name,
139
+ description=request.description,
140
+ source_deployment_id=request.source_deployment_id,
141
+ )
142
+
143
+ def update(self, update: RunTemplateUpdate) -> "RunTemplateSchema":
144
+ """Update the schema.
145
+
146
+ Args:
147
+ update: The update model.
148
+
149
+ Returns:
150
+ The updated schema.
151
+ """
152
+ for field, value in update.model_dump(
153
+ exclude_unset=True, exclude_none=True
154
+ ).items():
155
+ setattr(self, field, value)
156
+
157
+ self.updated = datetime.utcnow()
158
+ return self
159
+
160
+ def to_model(
161
+ self,
162
+ include_metadata: bool = False,
163
+ include_resources: bool = False,
164
+ **kwargs: Any,
165
+ ) -> RunTemplateResponse:
166
+ """Convert the schema to a response model.
167
+
168
+ Args:
169
+ include_metadata: Whether the metadata will be filled.
170
+ include_resources: Whether the resources will be filled.
171
+ **kwargs: Keyword arguments to allow schema specific logic
172
+
173
+ Returns:
174
+ Model representing this schema.
175
+ """
176
+ runnable = False
177
+ if (
178
+ self.source_deployment
179
+ and self.source_deployment.build
180
+ and self.source_deployment.build.stack
181
+ ):
182
+ runnable = True
183
+
184
+ body = RunTemplateResponseBody(
185
+ user=self.user.to_model() if self.user else None,
186
+ created=self.created,
187
+ updated=self.updated,
188
+ runnable=runnable,
189
+ latest_run_id=self.runs[-1].id if self.runs else None,
190
+ latest_run_status=self.runs[-1].status if self.runs else None,
191
+ )
192
+
193
+ metadata = None
194
+ if include_metadata:
195
+ pipeline_spec = None
196
+ config_template = None
197
+ config_schema = None
198
+
199
+ if self.source_deployment:
200
+ from zenml.zen_stores import template_utils
201
+
202
+ pipeline_spec = self.source_deployment.to_model(
203
+ include_metadata=True, include_resources=True
204
+ ).pipeline_spec
205
+
206
+ if (
207
+ self.source_deployment.build
208
+ and self.source_deployment.build.stack
209
+ ):
210
+ config_template = template_utils.generate_config_template(
211
+ deployment=self.source_deployment
212
+ )
213
+ config_schema = template_utils.generate_config_schema(
214
+ deployment=self.source_deployment
215
+ )
216
+
217
+ metadata = RunTemplateResponseMetadata(
218
+ workspace=self.workspace.to_model(),
219
+ description=self.description,
220
+ pipeline_spec=pipeline_spec,
221
+ config_template=config_template,
222
+ config_schema=config_schema,
223
+ )
224
+
225
+ resources = None
226
+ if include_resources:
227
+ if self.source_deployment:
228
+ pipeline = (
229
+ self.source_deployment.pipeline.to_model()
230
+ if self.source_deployment.pipeline
231
+ else None
232
+ )
233
+ build = (
234
+ self.source_deployment.build.to_model()
235
+ if self.source_deployment.build
236
+ else None
237
+ )
238
+ code_reference = (
239
+ self.source_deployment.code_reference.to_model()
240
+ if self.source_deployment.code_reference
241
+ else None
242
+ )
243
+ else:
244
+ pipeline = None
245
+ build = None
246
+ code_reference = None
247
+
248
+ resources = RunTemplateResponseResources(
249
+ source_deployment=self.source_deployment.to_model()
250
+ if self.source_deployment
251
+ else None,
252
+ pipeline=pipeline,
253
+ build=build,
254
+ code_reference=code_reference,
255
+ tags=[t.tag.to_model() for t in self.tags],
256
+ )
257
+
258
+ return RunTemplateResponse(
259
+ id=self.id,
260
+ name=self.name,
261
+ body=body,
262
+ metadata=metadata,
263
+ resources=resources,
264
+ )
@@ -274,11 +274,18 @@ class StepRunSchema(NamedSchema, table=True):
274
274
  if include_resources:
275
275
  model_version = None
276
276
  if full_step_config.config.model:
277
- model_version = (
278
- full_step_config.config.model._get_model_version(
279
- hydrate=False
277
+ # TODO: Why is there no ID check similar to
278
+ # PipelineRunSchema.to_model()?
279
+ try:
280
+ model_version = (
281
+ full_step_config.config.model._get_model_version(
282
+ hydrate=False
283
+ )
280
284
  )
281
- )
285
+ except KeyError:
286
+ # Unable to find the model version, it was probably deleted
287
+ pass
288
+
282
289
  resources = StepRunResponseResources(model_version=model_version)
283
290
 
284
291
  return StepRunResponse(