zenml-nightly 0.68.0.dev20241027__py3-none-any.whl → 0.68.1.dev20241101__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 +17 -11
- RELEASE_NOTES.md +9 -0
- zenml/VERSION +1 -1
- zenml/__init__.py +1 -1
- zenml/analytics/context.py +16 -1
- zenml/analytics/utils.py +18 -7
- zenml/artifacts/utils.py +40 -216
- zenml/cli/__init__.py +63 -90
- zenml/cli/base.py +3 -3
- zenml/cli/login.py +951 -0
- zenml/cli/server.py +462 -353
- zenml/cli/service_accounts.py +4 -4
- zenml/cli/stack.py +77 -2
- zenml/cli/stack_components.py +5 -16
- zenml/cli/user_management.py +0 -12
- zenml/cli/utils.py +24 -77
- zenml/client.py +46 -14
- zenml/config/compiler.py +1 -0
- zenml/config/global_config.py +9 -0
- zenml/config/pipeline_configurations.py +2 -1
- zenml/config/pipeline_run_configuration.py +2 -1
- zenml/constants.py +3 -9
- zenml/enums.py +1 -1
- zenml/exceptions.py +11 -0
- zenml/integrations/github/code_repositories/github_code_repository.py +1 -1
- zenml/login/__init__.py +16 -0
- zenml/login/credentials.py +346 -0
- zenml/login/credentials_store.py +603 -0
- zenml/login/pro/__init__.py +16 -0
- zenml/login/pro/client.py +496 -0
- zenml/login/pro/constants.py +34 -0
- zenml/login/pro/models.py +25 -0
- zenml/login/pro/organization/__init__.py +14 -0
- zenml/login/pro/organization/client.py +79 -0
- zenml/login/pro/organization/models.py +32 -0
- zenml/login/pro/tenant/__init__.py +14 -0
- zenml/login/pro/tenant/client.py +92 -0
- zenml/login/pro/tenant/models.py +174 -0
- zenml/login/pro/utils.py +121 -0
- zenml/{cli → login}/web_login.py +64 -28
- zenml/materializers/base_materializer.py +43 -9
- zenml/materializers/built_in_materializer.py +1 -1
- zenml/metadata/metadata_types.py +49 -0
- zenml/model/model.py +0 -38
- zenml/models/__init__.py +3 -0
- zenml/models/v2/base/base.py +12 -8
- zenml/models/v2/base/filter.py +9 -0
- zenml/models/v2/core/artifact_version.py +49 -10
- zenml/models/v2/core/component.py +54 -19
- zenml/models/v2/core/flavor.py +13 -13
- zenml/models/v2/core/model.py +3 -1
- zenml/models/v2/core/model_version.py +3 -5
- zenml/models/v2/core/model_version_artifact.py +3 -1
- zenml/models/v2/core/model_version_pipeline_run.py +3 -1
- zenml/models/v2/core/pipeline.py +3 -1
- zenml/models/v2/core/pipeline_run.py +23 -1
- zenml/models/v2/core/run_template.py +3 -1
- zenml/models/v2/core/stack.py +7 -3
- zenml/models/v2/core/step_run.py +43 -2
- zenml/models/v2/misc/auth_models.py +11 -2
- zenml/models/v2/misc/server_models.py +2 -0
- zenml/orchestrators/base_orchestrator.py +8 -4
- zenml/orchestrators/step_launcher.py +1 -0
- zenml/orchestrators/step_run_utils.py +10 -2
- zenml/orchestrators/step_runner.py +67 -55
- zenml/orchestrators/utils.py +45 -22
- zenml/pipelines/pipeline_decorator.py +5 -0
- zenml/pipelines/pipeline_definition.py +206 -160
- zenml/pipelines/run_utils.py +11 -10
- zenml/services/local/local_daemon_entrypoint.py +4 -4
- zenml/services/service.py +2 -2
- zenml/stack/stack.py +2 -6
- zenml/stack/stack_component.py +2 -7
- zenml/stack/utils.py +26 -14
- zenml/steps/base_step.py +8 -2
- zenml/steps/step_context.py +0 -3
- zenml/steps/step_invocation.py +14 -5
- zenml/steps/utils.py +1 -0
- zenml/utils/materializer_utils.py +1 -1
- zenml/utils/requirements_utils.py +71 -0
- zenml/utils/singleton.py +15 -3
- zenml/utils/source_utils.py +39 -2
- zenml/utils/visualization_utils.py +1 -1
- zenml/zen_server/auth.py +44 -39
- zenml/zen_server/deploy/__init__.py +7 -7
- zenml/zen_server/deploy/base_provider.py +46 -73
- zenml/zen_server/deploy/{local → daemon}/__init__.py +3 -3
- zenml/zen_server/deploy/{local/local_provider.py → daemon/daemon_provider.py} +44 -63
- zenml/zen_server/deploy/{local/local_zen_server.py → daemon/daemon_zen_server.py} +50 -22
- zenml/zen_server/deploy/deployer.py +90 -171
- zenml/zen_server/deploy/deployment.py +20 -12
- zenml/zen_server/deploy/docker/docker_provider.py +9 -28
- zenml/zen_server/deploy/docker/docker_zen_server.py +19 -3
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/exceptions.py +11 -0
- zenml/zen_server/jwt.py +9 -9
- zenml/zen_server/routers/auth_endpoints.py +30 -8
- zenml/zen_server/routers/stack_components_endpoints.py +1 -1
- zenml/zen_server/routers/workspaces_endpoints.py +1 -1
- zenml/zen_server/template_execution/runner_entrypoint_configuration.py +7 -4
- zenml/zen_server/template_execution/utils.py +6 -61
- zenml/zen_server/utils.py +64 -36
- zenml/zen_stores/base_zen_store.py +4 -49
- zenml/zen_stores/migrations/versions/0.68.1_release.py +23 -0
- zenml/zen_stores/migrations/versions/c22561cbb3a9_add_artifact_unique_constraints.py +86 -0
- zenml/zen_stores/rest_zen_store.py +325 -147
- zenml/zen_stores/schemas/api_key_schemas.py +9 -4
- zenml/zen_stores/schemas/artifact_schemas.py +21 -2
- zenml/zen_stores/schemas/artifact_visualization_schemas.py +1 -1
- zenml/zen_stores/schemas/component_schemas.py +49 -6
- zenml/zen_stores/schemas/device_schemas.py +9 -4
- zenml/zen_stores/schemas/flavor_schemas.py +1 -1
- zenml/zen_stores/schemas/model_schemas.py +1 -1
- zenml/zen_stores/schemas/service_schemas.py +1 -1
- zenml/zen_stores/schemas/step_run_schemas.py +1 -1
- zenml/zen_stores/schemas/trigger_schemas.py +1 -1
- zenml/zen_stores/sql_zen_store.py +393 -140
- zenml/zen_stores/template_utils.py +3 -1
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/METADATA +18 -12
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/RECORD +124 -107
- zenml/api.py +0 -60
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/entry_points.txt +0 -0
@@ -586,6 +586,7 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
586
586
|
"stack",
|
587
587
|
"code_repository",
|
588
588
|
"model",
|
589
|
+
"stack_component",
|
589
590
|
"pipeline_name",
|
590
591
|
"templatable",
|
591
592
|
]
|
@@ -688,6 +689,10 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
688
689
|
default=None,
|
689
690
|
description="Name/ID of the model associated with the run.",
|
690
691
|
)
|
692
|
+
stack_component: Optional[Union[UUID, str]] = Field(
|
693
|
+
default=None,
|
694
|
+
description="Name/ID of the stack component associated with the run.",
|
695
|
+
)
|
691
696
|
templatable: Optional[bool] = Field(
|
692
697
|
default=None, description="Whether the run is templatable."
|
693
698
|
)
|
@@ -716,6 +721,8 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
716
721
|
PipelineRunSchema,
|
717
722
|
PipelineSchema,
|
718
723
|
ScheduleSchema,
|
724
|
+
StackComponentSchema,
|
725
|
+
StackCompositionSchema,
|
719
726
|
StackSchema,
|
720
727
|
UserSchema,
|
721
728
|
)
|
@@ -772,7 +779,9 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
772
779
|
user_filter = and_(
|
773
780
|
PipelineRunSchema.user_id == UserSchema.id,
|
774
781
|
self.generate_name_or_id_query_conditions(
|
775
|
-
value=self.user,
|
782
|
+
value=self.user,
|
783
|
+
table=UserSchema,
|
784
|
+
additional_columns=["full_name"],
|
776
785
|
),
|
777
786
|
)
|
778
787
|
custom_filters.append(user_filter)
|
@@ -821,6 +830,19 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
|
|
821
830
|
)
|
822
831
|
custom_filters.append(model_filter)
|
823
832
|
|
833
|
+
if self.stack_component:
|
834
|
+
component_filter = and_(
|
835
|
+
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
|
836
|
+
PipelineDeploymentSchema.stack_id == StackSchema.id,
|
837
|
+
StackSchema.id == StackCompositionSchema.stack_id,
|
838
|
+
StackCompositionSchema.component_id == StackComponentSchema.id,
|
839
|
+
self.generate_name_or_id_query_conditions(
|
840
|
+
value=self.stack_component,
|
841
|
+
table=StackComponentSchema,
|
842
|
+
),
|
843
|
+
)
|
844
|
+
custom_filters.append(component_filter)
|
845
|
+
|
824
846
|
if self.pipeline_name:
|
825
847
|
pipeline_name_filter = and_(
|
826
848
|
PipelineRunSchema.pipeline_id == PipelineSchema.id,
|
@@ -413,7 +413,9 @@ class RunTemplateFilter(WorkspaceScopedTaggableFilter):
|
|
413
413
|
user_filter = and_(
|
414
414
|
RunTemplateSchema.user_id == UserSchema.id,
|
415
415
|
self.generate_name_or_id_query_conditions(
|
416
|
-
value=self.user,
|
416
|
+
value=self.user,
|
417
|
+
table=UserSchema,
|
418
|
+
additional_columns=["full_name"],
|
417
419
|
),
|
418
420
|
)
|
419
421
|
custom_filters.append(user_filter)
|
zenml/models/v2/core/stack.py
CHANGED
@@ -228,7 +228,7 @@ class StackResponse(
|
|
228
228
|
component_dict = dict(
|
229
229
|
name=component.name,
|
230
230
|
type=str(component.type),
|
231
|
-
flavor=component.
|
231
|
+
flavor=component.flavor_name,
|
232
232
|
)
|
233
233
|
configuration = json.loads(
|
234
234
|
component.get_metadata().model_dump_json(
|
@@ -255,7 +255,9 @@ class StackResponse(
|
|
255
255
|
Dict of analytics metadata.
|
256
256
|
"""
|
257
257
|
metadata = super().get_analytics_metadata()
|
258
|
-
metadata.update(
|
258
|
+
metadata.update(
|
259
|
+
{ct: c[0].flavor_name for ct, c in self.components.items()}
|
260
|
+
)
|
259
261
|
|
260
262
|
if self.labels is not None:
|
261
263
|
metadata.update(
|
@@ -381,7 +383,9 @@ class StackFilter(WorkspaceScopedFilter):
|
|
381
383
|
user_filter = and_(
|
382
384
|
StackSchema.user_id == UserSchema.id,
|
383
385
|
self.generate_name_or_id_query_conditions(
|
384
|
-
value=self.user,
|
386
|
+
value=self.user,
|
387
|
+
table=UserSchema,
|
388
|
+
additional_columns=["full_name"],
|
385
389
|
),
|
386
390
|
)
|
387
391
|
custom_filters.append(user_filter)
|
zenml/models/v2/core/step_run.py
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
"""Models representing steps runs."""
|
15
15
|
|
16
16
|
from datetime import datetime
|
17
|
-
from typing import TYPE_CHECKING, Dict, List, Optional, Union
|
17
|
+
from typing import TYPE_CHECKING, ClassVar, Dict, List, Optional, Union
|
18
18
|
from uuid import UUID
|
19
19
|
|
20
20
|
from pydantic import BaseModel, ConfigDict, Field
|
@@ -33,6 +33,8 @@ from zenml.models.v2.base.scoped import (
|
|
33
33
|
from zenml.models.v2.core.model_version import ModelVersionResponse
|
34
34
|
|
35
35
|
if TYPE_CHECKING:
|
36
|
+
from sqlalchemy.sql.elements import ColumnElement
|
37
|
+
|
36
38
|
from zenml.models.v2.core.artifact_version import ArtifactVersionResponse
|
37
39
|
from zenml.models.v2.core.logs import (
|
38
40
|
LogsRequest,
|
@@ -488,6 +490,11 @@ class StepRunResponse(
|
|
488
490
|
class StepRunFilter(WorkspaceScopedFilter):
|
489
491
|
"""Model to enable advanced filtering of step runs."""
|
490
492
|
|
493
|
+
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
|
494
|
+
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
|
495
|
+
"model",
|
496
|
+
]
|
497
|
+
|
491
498
|
name: Optional[str] = Field(
|
492
499
|
default=None,
|
493
500
|
description="Name of the step run",
|
@@ -541,8 +548,42 @@ class StepRunFilter(WorkspaceScopedFilter):
|
|
541
548
|
)
|
542
549
|
model_version_id: Optional[Union[UUID, str]] = Field(
|
543
550
|
default=None,
|
544
|
-
description="Model version associated with the
|
551
|
+
description="Model version associated with the step run.",
|
545
552
|
union_mode="left_to_right",
|
546
553
|
)
|
554
|
+
model: Optional[Union[UUID, str]] = Field(
|
555
|
+
default=None,
|
556
|
+
description="Name/ID of the model associated with the step run.",
|
557
|
+
)
|
547
558
|
|
548
559
|
model_config = ConfigDict(protected_namespaces=())
|
560
|
+
|
561
|
+
def get_custom_filters(
|
562
|
+
self,
|
563
|
+
) -> List["ColumnElement[bool]"]:
|
564
|
+
"""Get custom filters.
|
565
|
+
|
566
|
+
Returns:
|
567
|
+
A list of custom filters.
|
568
|
+
"""
|
569
|
+
custom_filters = super().get_custom_filters()
|
570
|
+
|
571
|
+
from sqlmodel import and_
|
572
|
+
|
573
|
+
from zenml.zen_stores.schemas import (
|
574
|
+
ModelSchema,
|
575
|
+
ModelVersionSchema,
|
576
|
+
StepRunSchema,
|
577
|
+
)
|
578
|
+
|
579
|
+
if self.model:
|
580
|
+
model_filter = and_(
|
581
|
+
StepRunSchema.model_version_id == ModelVersionSchema.id,
|
582
|
+
ModelVersionSchema.model_id == ModelSchema.id,
|
583
|
+
self.generate_name_or_id_query_conditions(
|
584
|
+
value=self.model, table=ModelSchema
|
585
|
+
),
|
586
|
+
)
|
587
|
+
custom_filters.append(model_filter)
|
588
|
+
|
589
|
+
return custom_filters
|
@@ -13,10 +13,10 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Models representing OAuth2 requests and responses."""
|
15
15
|
|
16
|
-
from typing import Optional
|
16
|
+
from typing import Any, Dict, Optional
|
17
17
|
from uuid import UUID
|
18
18
|
|
19
|
-
from pydantic import BaseModel
|
19
|
+
from pydantic import BaseModel, ConfigDict
|
20
20
|
|
21
21
|
from zenml.enums import OAuthGrantTypes
|
22
22
|
|
@@ -29,6 +29,7 @@ class OAuthDeviceAuthorizationRequest(BaseModel):
|
|
29
29
|
"""OAuth2 device authorization grant request."""
|
30
30
|
|
31
31
|
client_id: UUID
|
32
|
+
device_id: Optional[UUID] = None
|
32
33
|
|
33
34
|
|
34
35
|
class OAuthDeviceVerificationRequest(BaseModel):
|
@@ -119,6 +120,14 @@ class OAuthTokenResponse(BaseModel):
|
|
119
120
|
expires_in: Optional[int] = None
|
120
121
|
refresh_token: Optional[str] = None
|
121
122
|
scope: Optional[str] = None
|
123
|
+
cookie_name: Optional[str] = None
|
124
|
+
device_id: Optional[UUID] = None
|
125
|
+
device_metadata: Optional[Dict[str, Any]] = None
|
126
|
+
|
127
|
+
model_config = ConfigDict(
|
128
|
+
# Allow extra attributes to allow compatibility with different versions
|
129
|
+
extra="allow",
|
130
|
+
)
|
122
131
|
|
123
132
|
|
124
133
|
class OAuthRedirectResponse(BaseModel):
|
@@ -52,6 +52,8 @@ class ServerModel(BaseModel):
|
|
52
52
|
|
53
53
|
id: UUID = Field(default_factory=uuid4, title="The unique server id.")
|
54
54
|
|
55
|
+
name: Optional[str] = Field(None, title="The name of the ZenML server.")
|
56
|
+
|
55
57
|
version: str = Field(
|
56
58
|
title="The ZenML version that the server is running.",
|
57
59
|
)
|
@@ -166,9 +166,8 @@ class BaseOrchestrator(StackComponent, ABC):
|
|
166
166
|
environment: Environment variables to set in the orchestration
|
167
167
|
environment. These don't need to be set if running locally.
|
168
168
|
|
169
|
-
|
170
|
-
|
171
|
-
`pipeline_instance.run()` call when someone is running a pipeline.
|
169
|
+
Yields:
|
170
|
+
Metadata for the pipeline run.
|
172
171
|
"""
|
173
172
|
|
174
173
|
def run(
|
@@ -176,7 +175,7 @@ class BaseOrchestrator(StackComponent, ABC):
|
|
176
175
|
deployment: "PipelineDeploymentResponse",
|
177
176
|
stack: "Stack",
|
178
177
|
placeholder_run: Optional["PipelineRunResponse"] = None,
|
179
|
-
) ->
|
178
|
+
) -> None:
|
180
179
|
"""Runs a pipeline on a stack.
|
181
180
|
|
182
181
|
Args:
|
@@ -211,6 +210,11 @@ class BaseOrchestrator(StackComponent, ABC):
|
|
211
210
|
# the orchestrator does not try to run them
|
212
211
|
deployment.step_configurations.pop(invocation_id)
|
213
212
|
|
213
|
+
for step in deployment.step_configurations.values():
|
214
|
+
for invocation_id in cached_invocations:
|
215
|
+
if invocation_id in step.spec.upstream_steps:
|
216
|
+
step.spec.upstream_steps.remove(invocation_id)
|
217
|
+
|
214
218
|
if len(deployment.step_configurations) == 0:
|
215
219
|
# All steps were cached, we update the pipeline run status and
|
216
220
|
# don't actually use the orchestrator to run the pipeline
|
@@ -331,6 +331,7 @@ class StepLauncher:
|
|
331
331
|
status=ExecutionStatus.RUNNING,
|
332
332
|
orchestrator_environment=get_run_environment_dict(),
|
333
333
|
start_time=datetime.utcnow(),
|
334
|
+
tags=self._deployment.pipeline_configuration.tags,
|
334
335
|
)
|
335
336
|
return client.zen_store.get_or_create_run(pipeline_run)
|
336
337
|
|
@@ -35,7 +35,7 @@ from zenml.models import (
|
|
35
35
|
)
|
36
36
|
from zenml.orchestrators import cache_utils, input_utils, utils
|
37
37
|
from zenml.stack import Stack
|
38
|
-
from zenml.utils import string_utils
|
38
|
+
from zenml.utils import pagination_utils, string_utils
|
39
39
|
|
40
40
|
if TYPE_CHECKING:
|
41
41
|
from zenml.model.model import Model
|
@@ -424,7 +424,15 @@ def get_model_version_created_by_pipeline_run(
|
|
424
424
|
):
|
425
425
|
return pipeline_run.model_version
|
426
426
|
|
427
|
-
|
427
|
+
# We fetch a list of hydrated step runs here in order to avoid hydration
|
428
|
+
# calls for each step separately.
|
429
|
+
candidate_step_runs = pagination_utils.depaginate(
|
430
|
+
Client().list_run_steps,
|
431
|
+
pipeline_run_id=pipeline_run.id,
|
432
|
+
model=model_name,
|
433
|
+
hydrate=True,
|
434
|
+
)
|
435
|
+
for step_run in candidate_step_runs:
|
428
436
|
if step_run.config.model and step_run.model_version:
|
429
437
|
if (
|
430
438
|
step_run.config.model.name == model_name
|
@@ -57,6 +57,7 @@ from zenml.utils import materializer_utils, source_utils
|
|
57
57
|
from zenml.utils.typing_utils import get_origin, is_union
|
58
58
|
|
59
59
|
if TYPE_CHECKING:
|
60
|
+
from zenml.artifact_stores import BaseArtifactStore
|
60
61
|
from zenml.config.source import Source
|
61
62
|
from zenml.config.step_configurations import Step
|
62
63
|
from zenml.models import (
|
@@ -190,61 +191,62 @@ class StepRunner:
|
|
190
191
|
)
|
191
192
|
raise
|
192
193
|
finally:
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
publish_step_run_metadata(
|
197
|
-
step_run_id=step_run_info.step_run_id,
|
198
|
-
step_run_metadata=step_run_metadata,
|
199
|
-
)
|
200
|
-
self._stack.cleanup_step_run(
|
201
|
-
info=step_run_info, step_failed=step_failed
|
202
|
-
)
|
203
|
-
if not step_failed:
|
204
|
-
if (
|
205
|
-
success_hook_source
|
206
|
-
:= self.configuration.success_hook_source
|
207
|
-
):
|
208
|
-
logger.info("Detected success hook. Running...")
|
209
|
-
self.load_and_run_hook(
|
210
|
-
success_hook_source,
|
211
|
-
step_exception=None,
|
212
|
-
)
|
213
|
-
|
214
|
-
# Store and publish the output artifacts of the step function.
|
215
|
-
output_data = self._validate_outputs(
|
216
|
-
return_values, output_annotations
|
194
|
+
try:
|
195
|
+
step_run_metadata = self._stack.get_step_run_metadata(
|
196
|
+
info=step_run_info,
|
217
197
|
)
|
218
|
-
|
219
|
-
|
220
|
-
|
198
|
+
publish_step_run_metadata(
|
199
|
+
step_run_id=step_run_info.step_run_id,
|
200
|
+
step_run_metadata=step_run_metadata,
|
221
201
|
)
|
222
|
-
|
223
|
-
|
224
|
-
is_enabled_on_pipeline=step_run_info.pipeline.enable_artifact_visualization,
|
202
|
+
self._stack.cleanup_step_run(
|
203
|
+
info=step_run_info, step_failed=step_failed
|
225
204
|
)
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
205
|
+
if not step_failed:
|
206
|
+
if (
|
207
|
+
success_hook_source
|
208
|
+
:= self.configuration.success_hook_source
|
209
|
+
):
|
210
|
+
logger.info("Detected success hook. Running...")
|
211
|
+
self.load_and_run_hook(
|
212
|
+
success_hook_source,
|
213
|
+
step_exception=None,
|
214
|
+
)
|
215
|
+
|
216
|
+
# Store and publish the output artifacts of the step function.
|
217
|
+
output_data = self._validate_outputs(
|
218
|
+
return_values, output_annotations
|
219
|
+
)
|
220
|
+
artifact_metadata_enabled = is_setting_enabled(
|
221
|
+
is_enabled_on_step=step_run_info.config.enable_artifact_metadata,
|
222
|
+
is_enabled_on_pipeline=step_run_info.pipeline.enable_artifact_metadata,
|
223
|
+
)
|
224
|
+
artifact_visualization_enabled = is_setting_enabled(
|
225
|
+
is_enabled_on_step=step_run_info.config.enable_artifact_visualization,
|
226
|
+
is_enabled_on_pipeline=step_run_info.pipeline.enable_artifact_visualization,
|
245
227
|
)
|
228
|
+
output_artifacts = self._store_output_artifacts(
|
229
|
+
output_data=output_data,
|
230
|
+
output_artifact_uris=output_artifact_uris,
|
231
|
+
output_materializers=output_materializers,
|
232
|
+
output_annotations=output_annotations,
|
233
|
+
artifact_metadata_enabled=artifact_metadata_enabled,
|
234
|
+
artifact_visualization_enabled=artifact_visualization_enabled,
|
235
|
+
)
|
236
|
+
|
237
|
+
if (
|
238
|
+
model_version := step_run.model_version
|
239
|
+
or pipeline_run.model_version
|
240
|
+
):
|
241
|
+
from zenml.orchestrators import step_run_utils
|
246
242
|
|
247
|
-
|
243
|
+
step_run_utils.link_output_artifacts_to_model_version(
|
244
|
+
artifacts=output_artifacts,
|
245
|
+
output_configurations=step_run.config.outputs,
|
246
|
+
model_version=model_version,
|
247
|
+
)
|
248
|
+
finally:
|
249
|
+
StepContext._clear() # Remove the step context singleton
|
248
250
|
|
249
251
|
# Update the status and output artifacts of the step run.
|
250
252
|
output_artifact_ids = {
|
@@ -406,15 +408,25 @@ class StepRunner:
|
|
406
408
|
)
|
407
409
|
)
|
408
410
|
|
409
|
-
|
410
|
-
artifact.artifact_store_id
|
411
|
-
) as target_artifact_store:
|
411
|
+
def _load_artifact(artifact_store: "BaseArtifactStore") -> Any:
|
412
412
|
materializer: BaseMaterializer = materializer_class(
|
413
|
-
uri=artifact.uri, artifact_store=
|
413
|
+
uri=artifact.uri, artifact_store=artifact_store
|
414
414
|
)
|
415
|
-
materializer.
|
415
|
+
materializer.validate_load_type_compatibility(data_type)
|
416
416
|
return materializer.load(data_type=data_type)
|
417
417
|
|
418
|
+
if artifact.artifact_store_id == self._stack.artifact_store.id:
|
419
|
+
# Register the artifact store of the active stack here to avoid
|
420
|
+
# unnecessary component/flavor calls when using
|
421
|
+
# `register_artifact_store_filesystem(...)`
|
422
|
+
self._stack.artifact_store._register()
|
423
|
+
return _load_artifact(artifact_store=self._stack.artifact_store)
|
424
|
+
else:
|
425
|
+
with register_artifact_store_filesystem(
|
426
|
+
artifact.artifact_store_id
|
427
|
+
) as target_artifact_store:
|
428
|
+
return _load_artifact(artifact_store=target_artifact_store)
|
429
|
+
|
418
430
|
def _validate_outputs(
|
419
431
|
self,
|
420
432
|
return_values: Any,
|
zenml/orchestrators/utils.py
CHANGED
@@ -25,11 +25,12 @@ from zenml.config.global_config import (
|
|
25
25
|
from zenml.constants import (
|
26
26
|
ENV_ZENML_ACTIVE_STACK_ID,
|
27
27
|
ENV_ZENML_ACTIVE_WORKSPACE_ID,
|
28
|
+
ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING,
|
28
29
|
ENV_ZENML_SERVER,
|
29
30
|
ENV_ZENML_STORE_PREFIX,
|
30
31
|
PIPELINE_API_TOKEN_EXPIRES_MINUTES,
|
31
32
|
)
|
32
|
-
from zenml.enums import StackComponentType, StoreType
|
33
|
+
from zenml.enums import AuthScheme, StackComponentType, StoreType
|
33
34
|
from zenml.logger import get_logger
|
34
35
|
from zenml.stack import StackComponent
|
35
36
|
from zenml.utils.string_utils import format_name_template
|
@@ -93,32 +94,54 @@ def get_config_environment_vars(
|
|
93
94
|
Returns:
|
94
95
|
Environment variable dict.
|
95
96
|
"""
|
97
|
+
from zenml.login.credentials_store import get_credentials_store
|
96
98
|
from zenml.zen_stores.rest_zen_store import RestZenStore
|
97
99
|
|
98
100
|
global_config = GlobalConfiguration()
|
99
101
|
environment_vars = global_config.get_config_environment_vars()
|
100
102
|
|
101
|
-
if
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
#
|
114
|
-
#
|
115
|
-
|
116
|
-
|
117
|
-
pipeline_id=
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
103
|
+
if (
|
104
|
+
global_config.store_configuration.type == StoreType.REST
|
105
|
+
and global_config.zen_store.get_store_info().auth_scheme
|
106
|
+
!= AuthScheme.NO_AUTH
|
107
|
+
):
|
108
|
+
credentials_store = get_credentials_store()
|
109
|
+
url = global_config.store_configuration.url
|
110
|
+
api_key = credentials_store.get_api_key(url)
|
111
|
+
api_token = credentials_store.get_token(url, allow_expired=False)
|
112
|
+
if api_key:
|
113
|
+
environment_vars[ENV_ZENML_STORE_PREFIX + "API_KEY"] = api_key
|
114
|
+
elif deployment:
|
115
|
+
# When connected to an authenticated ZenML server, if a pipeline
|
116
|
+
# deployment is supplied, we need to fetch an API token that will be
|
117
|
+
# valid for the duration of the pipeline run.
|
118
|
+
assert isinstance(global_config.zen_store, RestZenStore)
|
119
|
+
pipeline_id: Optional[UUID] = None
|
120
|
+
if deployment.pipeline:
|
121
|
+
pipeline_id = deployment.pipeline.id
|
122
|
+
schedule_id: Optional[UUID] = None
|
123
|
+
expires_minutes: Optional[int] = PIPELINE_API_TOKEN_EXPIRES_MINUTES
|
124
|
+
if deployment.schedule:
|
125
|
+
schedule_id = deployment.schedule.id
|
126
|
+
# If a schedule is given, this is a long running pipeline that
|
127
|
+
# should not have an API token that expires.
|
128
|
+
expires_minutes = None
|
129
|
+
new_api_token = global_config.zen_store.get_api_token(
|
130
|
+
pipeline_id=pipeline_id,
|
131
|
+
schedule_id=schedule_id,
|
132
|
+
expires_minutes=expires_minutes,
|
133
|
+
)
|
134
|
+
environment_vars[ENV_ZENML_STORE_PREFIX + "API_TOKEN"] = (
|
135
|
+
new_api_token
|
136
|
+
)
|
137
|
+
elif api_token:
|
138
|
+
environment_vars[ENV_ZENML_STORE_PREFIX + "API_TOKEN"] = (
|
139
|
+
api_token.access_token
|
140
|
+
)
|
141
|
+
|
142
|
+
# Disable credentials caching to avoid storing sensitive information
|
143
|
+
# in the pipeline run environment
|
144
|
+
environment_vars[ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING] = "true"
|
122
145
|
|
123
146
|
# Make sure to use the correct active stack/workspace which might come
|
124
147
|
# from a .zen repository and not the global config
|
@@ -18,6 +18,7 @@ from typing import (
|
|
18
18
|
Any,
|
19
19
|
Callable,
|
20
20
|
Dict,
|
21
|
+
List,
|
21
22
|
Optional,
|
22
23
|
TypeVar,
|
23
24
|
Union,
|
@@ -49,6 +50,7 @@ def pipeline(
|
|
49
50
|
enable_artifact_metadata: Optional[bool] = None,
|
50
51
|
enable_step_logs: Optional[bool] = None,
|
51
52
|
settings: Optional[Dict[str, "SettingsOrDict"]] = None,
|
53
|
+
tags: Optional[List[str]] = None,
|
52
54
|
extra: Optional[Dict[str, Any]] = None,
|
53
55
|
on_failure: Optional["HookSpecification"] = None,
|
54
56
|
on_success: Optional["HookSpecification"] = None,
|
@@ -64,6 +66,7 @@ def pipeline(
|
|
64
66
|
enable_artifact_metadata: Optional[bool] = None,
|
65
67
|
enable_step_logs: Optional[bool] = None,
|
66
68
|
settings: Optional[Dict[str, "SettingsOrDict"]] = None,
|
69
|
+
tags: Optional[List[str]] = None,
|
67
70
|
extra: Optional[Dict[str, Any]] = None,
|
68
71
|
on_failure: Optional["HookSpecification"] = None,
|
69
72
|
on_success: Optional["HookSpecification"] = None,
|
@@ -79,6 +82,7 @@ def pipeline(
|
|
79
82
|
enable_artifact_metadata: Whether to enable artifact metadata or not.
|
80
83
|
enable_step_logs: If step logs should be enabled for this pipeline.
|
81
84
|
settings: Settings for this pipeline.
|
85
|
+
tags: Tags to apply to runs of the pipeline.
|
82
86
|
extra: Extra configurations for this pipeline.
|
83
87
|
on_failure: Callback function in event of failure of the step. Can be a
|
84
88
|
function with a single argument of type `BaseException`, or a source
|
@@ -101,6 +105,7 @@ def pipeline(
|
|
101
105
|
enable_artifact_metadata=enable_artifact_metadata,
|
102
106
|
enable_step_logs=enable_step_logs,
|
103
107
|
settings=settings,
|
108
|
+
tags=tags,
|
104
109
|
extra=extra,
|
105
110
|
on_failure=on_failure,
|
106
111
|
on_success=on_success,
|