zenml-nightly 0.62.0.dev20240726__py3-none-any.whl → 0.62.0.dev20240727__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.
zenml/VERSION CHANGED
@@ -1 +1 @@
1
- 0.62.0.dev20240726
1
+ 0.62.0.dev20240727
@@ -16,7 +16,7 @@
16
16
  import json
17
17
  from typing import Any, Dict, List, Optional
18
18
 
19
- from zenml.config.source import Source
19
+ from zenml.config.source import Source, SourceWithValidator
20
20
  from zenml.config.step_configurations import StepSpec
21
21
  from zenml.config.strict_base_model import StrictBaseModel
22
22
  from zenml.utils.json_utils import pydantic_encoder
@@ -34,7 +34,7 @@ class PipelineSpec(StrictBaseModel):
34
34
  # - 0.4: New Pipeline class, the upstream steps and
35
35
  # inputs in the step specs refer to the pipeline parameter names
36
36
  version: str = "0.4"
37
- source: Optional[Source] = None
37
+ source: Optional[SourceWithValidator] = None
38
38
  parameters: Dict[str, Any] = {}
39
39
  steps: List[StepSpec]
40
40
 
@@ -55,10 +55,10 @@ logger = get_logger(__name__)
55
55
  class PartialArtifactConfiguration(StrictBaseModel):
56
56
  """Class representing a partial input/output artifact configuration."""
57
57
 
58
- materializer_source: Optional[Tuple[Source, ...]] = None
58
+ materializer_source: Optional[Tuple[SourceWithValidator, ...]] = None
59
59
  # TODO: This could be moved to the `PipelineDeployment` as it's the same
60
60
  # for all steps/outputs
61
- default_materializer_source: Optional[Source] = None
61
+ default_materializer_source: Optional[SourceWithValidator] = None
62
62
 
63
63
  @model_validator(mode="before")
64
64
  @classmethod
@@ -109,7 +109,7 @@ class PartialArtifactConfiguration(StrictBaseModel):
109
109
  class ArtifactConfiguration(PartialArtifactConfiguration):
110
110
  """Class representing a complete input/output artifact configuration."""
111
111
 
112
- materializer_source: Tuple[Source, ...]
112
+ materializer_source: Tuple[SourceWithValidator, ...]
113
113
 
114
114
  @field_validator("materializer_source", mode="before")
115
115
  @classmethod
@@ -363,7 +363,6 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
363
363
  pipeline_func
364
364
  """
365
365
  step_name_to_dynamic_component: Dict[str, Any] = {}
366
- node_selector_constraint: Optional[Tuple[str, str]] = None
367
366
 
368
367
  for step_name, step in deployment.step_configurations.items():
369
368
  image = self.get_image(
@@ -410,23 +409,17 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
410
409
  "Volume mounts are set but not supported in "
411
410
  "Vertex with Kubeflow Pipelines 2.x. Ignoring..."
412
411
  )
413
-
414
- # apply pod settings
415
- if (
416
- GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
417
- in pod_settings.node_selectors.keys()
418
- ):
419
- node_selector_constraint = (
420
- GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL,
421
- pod_settings.node_selectors[
422
- GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
423
- ],
424
- )
425
- elif step_settings.node_selector_constraint:
426
- node_selector_constraint = (
427
- GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL,
428
- step_settings.node_selector_constraint[1],
429
- )
412
+ for key in pod_settings.node_selectors:
413
+ if (
414
+ key
415
+ != GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
416
+ ):
417
+ logger.warning(
418
+ "Vertex only allows the %s node selector, "
419
+ "ignoring the node selector %s.",
420
+ GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL,
421
+ key,
422
+ )
430
423
 
431
424
  step_name_to_dynamic_component[step_name] = dynamic_component
432
425
 
@@ -460,10 +453,33 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
460
453
  )
461
454
  .after(*upstream_step_components)
462
455
  )
456
+
457
+ step_settings = cast(
458
+ VertexOrchestratorSettings, self.get_settings(step)
459
+ )
460
+ pod_settings = step_settings.pod_settings
461
+
462
+ node_selector_constraint: Optional[Tuple[str, str]] = None
463
+ if pod_settings and (
464
+ GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
465
+ in pod_settings.node_selectors.keys()
466
+ ):
467
+ node_selector_constraint = (
468
+ GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL,
469
+ pod_settings.node_selectors[
470
+ GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
471
+ ],
472
+ )
473
+ elif step_settings.node_selector_constraint:
474
+ node_selector_constraint = (
475
+ GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL,
476
+ step_settings.node_selector_constraint[1],
477
+ )
478
+
463
479
  self._configure_container_resources(
464
- task,
465
- step.config.resource_settings,
466
- node_selector_constraint,
480
+ dynamic_component=task,
481
+ resource_settings=step.config.resource_settings,
482
+ node_selector_constraint=node_selector_constraint,
467
483
  )
468
484
 
469
485
  return dynamic_pipeline
@@ -731,20 +747,20 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
731
747
  )
732
748
 
733
749
  if node_selector_constraint:
734
- (constraint_label, value) = node_selector_constraint
750
+ _, value = node_selector_constraint
735
751
  if gpu_limit is not None and gpu_limit > 0:
736
752
  dynamic_component = (
737
753
  dynamic_component.set_accelerator_type(value)
738
754
  .set_accelerator_limit(gpu_limit)
739
755
  .set_gpu_limit(gpu_limit)
740
756
  )
741
- elif (
742
- constraint_label
743
- == GKE_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
744
- and gpu_limit == 0
745
- ):
757
+ else:
746
758
  logger.warning(
747
- "GPU limit is set to 0 but a GPU type is specified. Ignoring GPU settings."
759
+ "Accelerator type %s specified, but the GPU limit is not "
760
+ "set or set to 0. The accelerator type will be ignored. "
761
+ "To fix this warning, either remove the specified "
762
+ "accelerator type or set the `gpu_count` using the "
763
+ "ResourceSettings (https://docs.zenml.io/how-to/training-with-gpus#specify-resource-requirements-for-steps)."
748
764
  )
749
765
 
750
766
  return dynamic_component
@@ -24,6 +24,7 @@ from zenml.integrations.integration import Integration
24
24
  from zenml.stack import Flavor
25
25
 
26
26
  KUBERNETES_ORCHESTRATOR_FLAVOR = "kubernetes"
27
+ KUBERNETES_STEP_OPERATOR_FLAVOR = "kubernetes"
27
28
 
28
29
 
29
30
  class KubernetesIntegration(Integration):
@@ -42,10 +43,10 @@ class KubernetesIntegration(Integration):
42
43
  List of new stack component flavors.
43
44
  """
44
45
  from zenml.integrations.kubernetes.flavors import (
45
- KubernetesOrchestratorFlavor,
46
+ KubernetesOrchestratorFlavor, KubernetesStepOperatorFlavor
46
47
  )
47
48
 
48
- return [KubernetesOrchestratorFlavor]
49
+ return [KubernetesOrchestratorFlavor, KubernetesStepOperatorFlavor]
49
50
 
50
51
 
51
52
  KubernetesIntegration.check_installation()
@@ -18,9 +18,17 @@ from zenml.integrations.kubernetes.flavors.kubernetes_orchestrator_flavor import
18
18
  KubernetesOrchestratorFlavor,
19
19
  KubernetesOrchestratorSettings,
20
20
  )
21
+ from zenml.integrations.kubernetes.flavors.kubernetes_step_operator_flavor import (
22
+ KubernetesStepOperatorConfig,
23
+ KubernetesStepOperatorFlavor,
24
+ KubernetesStepOperatorSettings,
25
+ )
21
26
 
22
27
  __all__ = [
23
28
  "KubernetesOrchestratorFlavor",
24
29
  "KubernetesOrchestratorConfig",
25
30
  "KubernetesOrchestratorSettings",
31
+ "KubernetesStepOperatorConfig",
32
+ "KubernetesStepOperatorFlavor",
33
+ "KubernetesStepOperatorSettings",
26
34
  ]
@@ -0,0 +1,166 @@
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
+ """Kubernetes step operator flavor."""
15
+
16
+ from typing import TYPE_CHECKING, Optional, Type
17
+
18
+ from zenml.config.base_settings import BaseSettings
19
+ from zenml.constants import KUBERNETES_CLUSTER_RESOURCE_TYPE
20
+ from zenml.integrations.kubernetes import KUBERNETES_STEP_OPERATOR_FLAVOR
21
+ from zenml.integrations.kubernetes.pod_settings import KubernetesPodSettings
22
+ from zenml.models import ServiceConnectorRequirements
23
+ from zenml.step_operators import BaseStepOperatorConfig, BaseStepOperatorFlavor
24
+
25
+ if TYPE_CHECKING:
26
+ from zenml.integrations.kubernetes.step_operators import (
27
+ KubernetesStepOperator,
28
+ )
29
+
30
+
31
+ class KubernetesStepOperatorSettings(BaseSettings):
32
+ """Settings for the Kubernetes step operator.
33
+
34
+ Attributes:
35
+ pod_settings: Pod settings to apply to pods executing the steps.
36
+ service_account_name: Name of the service account to use for the pod.
37
+ privileged: If the container should be run in privileged mode.
38
+ """
39
+
40
+ pod_settings: Optional[KubernetesPodSettings] = None
41
+ service_account_name: Optional[str] = None
42
+ privileged: bool = False
43
+
44
+
45
+ class KubernetesStepOperatorConfig(
46
+ BaseStepOperatorConfig, KubernetesStepOperatorSettings
47
+ ):
48
+ """Configuration for the Kubernetes step operator.
49
+
50
+ Attributes:
51
+ kubernetes_namespace: Name of the Kubernetes namespace to be used.
52
+ incluster: If `True`, the step operator will run the pipeline inside the
53
+ same cluster in which the orchestrator is running. For this to work,
54
+ the pod running the orchestrator needs permissions to create new
55
+ pods. If set, the `kubernetes_context` config option is ignored. If
56
+ the stack component is linked to a Kubernetes service connector,
57
+ this field is ignored.
58
+ kubernetes_context: Name of a Kubernetes context to run pipelines in.
59
+ If the stack component is linked to a Kubernetes service connector,
60
+ this field is ignored. Otherwise, it is mandatory.
61
+ """
62
+
63
+ kubernetes_namespace: str = "zenml"
64
+ incluster: bool = False
65
+ kubernetes_context: Optional[str] = None
66
+
67
+ @property
68
+ def is_remote(self) -> bool:
69
+ """Checks if this stack component is running remotely.
70
+
71
+ This designation is used to determine if the stack component can be
72
+ used with a local ZenML database or if it requires a remote ZenML
73
+ server.
74
+
75
+ Returns:
76
+ True if this config is for a remote component, False otherwise.
77
+ """
78
+ return True
79
+
80
+ @property
81
+ def is_local(self) -> bool:
82
+ """Checks if this stack component is running locally.
83
+
84
+ Returns:
85
+ True if this config is for a local component, False otherwise.
86
+ """
87
+ return False
88
+
89
+
90
+ class KubernetesStepOperatorFlavor(BaseStepOperatorFlavor):
91
+ """Kubernetes step operator flavor."""
92
+
93
+ @property
94
+ def name(self) -> str:
95
+ """Name of the flavor.
96
+
97
+ Returns:
98
+ The name of the flavor.
99
+ """
100
+ return KUBERNETES_STEP_OPERATOR_FLAVOR
101
+
102
+ @property
103
+ def service_connector_requirements(
104
+ self,
105
+ ) -> Optional[ServiceConnectorRequirements]:
106
+ """Service connector resource requirements for service connectors.
107
+
108
+ Specifies resource requirements that are used to filter the available
109
+ service connector types that are compatible with this flavor.
110
+
111
+ Returns:
112
+ Requirements for compatible service connectors, if a service
113
+ connector is required for this flavor.
114
+ """
115
+ return ServiceConnectorRequirements(
116
+ resource_type=KUBERNETES_CLUSTER_RESOURCE_TYPE,
117
+ )
118
+
119
+ @property
120
+ def docs_url(self) -> Optional[str]:
121
+ """A url to point at docs explaining this flavor.
122
+
123
+ Returns:
124
+ A flavor docs url.
125
+ """
126
+ return self.generate_default_docs_url()
127
+
128
+ @property
129
+ def sdk_docs_url(self) -> Optional[str]:
130
+ """A url to point at SDK docs explaining this flavor.
131
+
132
+ Returns:
133
+ A flavor SDK docs url.
134
+ """
135
+ return self.generate_default_sdk_docs_url()
136
+
137
+ @property
138
+ def logo_url(self) -> str:
139
+ """A url to represent the flavor in the dashboard.
140
+
141
+ Returns:
142
+ The flavor logo.
143
+ """
144
+ return "https://public-flavor-logos.s3.eu-central-1.amazonaws.com/step_operator/kubernetes.png"
145
+
146
+ @property
147
+ def config_class(self) -> Type[KubernetesStepOperatorConfig]:
148
+ """Returns `KubernetesStepOperatorConfig` config class.
149
+
150
+ Returns:
151
+ The config class.
152
+ """
153
+ return KubernetesStepOperatorConfig
154
+
155
+ @property
156
+ def implementation_class(self) -> Type["KubernetesStepOperator"]:
157
+ """Implementation class for this flavor.
158
+
159
+ Returns:
160
+ The implementation class.
161
+ """
162
+ from zenml.integrations.kubernetes.step_operators import (
163
+ KubernetesStepOperator,
164
+ )
165
+
166
+ return KubernetesStepOperator
@@ -0,0 +1,22 @@
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
+ """Kubernetes step operator."""
15
+
16
+ from zenml.integrations.kubernetes.step_operators.kubernetes_step_operator import (
17
+ KubernetesStepOperator,
18
+ )
19
+
20
+ __all__ = [
21
+ "KubernetesStepOperator",
22
+ ]
@@ -0,0 +1,235 @@
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
+ """Kubernetes step operator implementation."""
15
+
16
+ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type, cast
17
+
18
+ from kubernetes import client as k8s_client
19
+
20
+ from zenml.config.base_settings import BaseSettings
21
+ from zenml.config.build_configuration import BuildConfiguration
22
+ from zenml.enums import StackComponentType
23
+ from zenml.integrations.kubernetes.flavors import (
24
+ KubernetesStepOperatorConfig,
25
+ KubernetesStepOperatorSettings,
26
+ )
27
+ from zenml.integrations.kubernetes.orchestrators import kube_utils
28
+ from zenml.integrations.kubernetes.orchestrators.manifest_utils import (
29
+ build_pod_manifest,
30
+ )
31
+ from zenml.logger import get_logger
32
+ from zenml.stack import Stack, StackValidator
33
+ from zenml.step_operators import BaseStepOperator
34
+
35
+ if TYPE_CHECKING:
36
+ from zenml.config.base_settings import BaseSettings
37
+ from zenml.config.step_run_info import StepRunInfo
38
+ from zenml.models import PipelineDeploymentBase
39
+
40
+ logger = get_logger(__name__)
41
+
42
+ KUBERNETES_STEP_OPERATOR_DOCKER_IMAGE_KEY = "kubernetes_step_operator"
43
+
44
+
45
+ class KubernetesStepOperator(BaseStepOperator):
46
+ """Step operator to run on Kubernetes."""
47
+
48
+ _k8s_client: Optional[k8s_client.ApiClient] = None
49
+
50
+ @property
51
+ def config(self) -> KubernetesStepOperatorConfig:
52
+ """Returns the `KubernetesStepOperatorConfig` config.
53
+
54
+ Returns:
55
+ The configuration.
56
+ """
57
+ return cast(KubernetesStepOperatorConfig, self._config)
58
+
59
+ @property
60
+ def settings_class(self) -> Optional[Type["BaseSettings"]]:
61
+ """Settings class for the Kubernetes step operator.
62
+
63
+ Returns:
64
+ The settings class.
65
+ """
66
+ return KubernetesStepOperatorSettings
67
+
68
+ @property
69
+ def validator(self) -> Optional[StackValidator]:
70
+ """Validates the stack.
71
+
72
+ Returns:
73
+ A validator that checks that the stack contains a remote container
74
+ registry and a remote artifact store.
75
+ """
76
+
77
+ def _validate_remote_components(stack: "Stack") -> Tuple[bool, str]:
78
+ if stack.artifact_store.config.is_local:
79
+ return False, (
80
+ "The Kubernetes step operator runs code remotely and "
81
+ "needs to write files into the artifact store, but the "
82
+ f"artifact store `{stack.artifact_store.name}` of the "
83
+ "active stack is local. Please ensure that your stack "
84
+ "contains a remote artifact store when using the Vertex "
85
+ "step operator."
86
+ )
87
+
88
+ container_registry = stack.container_registry
89
+ assert container_registry is not None
90
+
91
+ if container_registry.config.is_local:
92
+ return False, (
93
+ "The Kubernetes step operator runs code remotely and "
94
+ "needs to push/pull Docker images, but the "
95
+ f"container registry `{container_registry.name}` of the "
96
+ "active stack is local. Please ensure that your stack "
97
+ "contains a remote container registry when using the "
98
+ "Kubernetes step operator."
99
+ )
100
+
101
+ return True, ""
102
+
103
+ return StackValidator(
104
+ required_components={
105
+ StackComponentType.CONTAINER_REGISTRY,
106
+ StackComponentType.IMAGE_BUILDER,
107
+ },
108
+ custom_validation_function=_validate_remote_components,
109
+ )
110
+
111
+ def get_docker_builds(
112
+ self, deployment: "PipelineDeploymentBase"
113
+ ) -> List["BuildConfiguration"]:
114
+ """Gets the Docker builds required for the component.
115
+
116
+ Args:
117
+ deployment: The pipeline deployment for which to get the builds.
118
+
119
+ Returns:
120
+ The required Docker builds.
121
+ """
122
+ builds = []
123
+ for step_name, step in deployment.step_configurations.items():
124
+ if step.config.step_operator == self.name:
125
+ build = BuildConfiguration(
126
+ key=KUBERNETES_STEP_OPERATOR_DOCKER_IMAGE_KEY,
127
+ settings=step.config.docker_settings,
128
+ step_name=step_name,
129
+ )
130
+ builds.append(build)
131
+
132
+ return builds
133
+
134
+ def get_kube_client(self) -> k8s_client.ApiClient:
135
+ """Get the Kubernetes API client.
136
+
137
+ Returns:
138
+ The Kubernetes API client.
139
+
140
+ Raises:
141
+ RuntimeError: If the service connector returns an unexpected client.
142
+ """
143
+ if self.config.incluster:
144
+ kube_utils.load_kube_config(incluster=True)
145
+ self._k8s_client = k8s_client.ApiClient()
146
+ return self._k8s_client
147
+
148
+ # Refresh the client also if the connector has expired
149
+ if self._k8s_client and not self.connector_has_expired():
150
+ return self._k8s_client
151
+
152
+ connector = self.get_connector()
153
+ if connector:
154
+ client = connector.connect()
155
+ if not isinstance(client, k8s_client.ApiClient):
156
+ raise RuntimeError(
157
+ f"Expected a k8s_client.ApiClient while trying to use the "
158
+ f"linked connector, but got {type(client)}."
159
+ )
160
+ self._k8s_client = client
161
+ else:
162
+ kube_utils.load_kube_config(
163
+ context=self.config.kubernetes_context,
164
+ )
165
+ self._k8s_client = k8s_client.ApiClient()
166
+
167
+ return self._k8s_client
168
+
169
+ @property
170
+ def _k8s_core_api(self) -> k8s_client.CoreV1Api:
171
+ """Getter for the Kubernetes Core API client.
172
+
173
+ Returns:
174
+ The Kubernetes Core API client.
175
+ """
176
+ return k8s_client.CoreV1Api(self.get_kube_client())
177
+
178
+ def launch(
179
+ self,
180
+ info: "StepRunInfo",
181
+ entrypoint_command: List[str],
182
+ environment: Dict[str, str],
183
+ ) -> None:
184
+ """Launches a step on Kubernetes.
185
+
186
+ Args:
187
+ info: Information about the step run.
188
+ entrypoint_command: Command that executes the step.
189
+ environment: Environment variables to set in the step operator
190
+ environment.
191
+ """
192
+ settings = cast(
193
+ KubernetesStepOperatorSettings, self.get_settings(info)
194
+ )
195
+ image_name = info.get_image(
196
+ key=KUBERNETES_STEP_OPERATOR_DOCKER_IMAGE_KEY
197
+ )
198
+
199
+ pod_name = f"{info.run_name}_{info.pipeline_step_name}"
200
+ pod_name = kube_utils.sanitize_pod_name(pod_name)
201
+
202
+ command = entrypoint_command[:3]
203
+ args = entrypoint_command[3:]
204
+
205
+ # Create and run the orchestrator pod.
206
+ pod_manifest = build_pod_manifest(
207
+ run_name=info.run_name,
208
+ pod_name=pod_name,
209
+ pipeline_name=info.pipeline.name,
210
+ image_name=image_name,
211
+ command=command,
212
+ args=args,
213
+ privileged=settings.privileged,
214
+ service_account_name=settings.service_account_name,
215
+ pod_settings=settings.pod_settings,
216
+ env=environment,
217
+ mount_local_stores=False,
218
+ )
219
+
220
+ self._k8s_core_api.create_namespaced_pod(
221
+ namespace=self.config.kubernetes_namespace,
222
+ body=pod_manifest,
223
+ )
224
+
225
+ logger.info(
226
+ "Waiting for pod of step `%s` to start...", info.pipeline_step_name
227
+ )
228
+ kube_utils.wait_pod(
229
+ kube_client_fn=self.get_kube_client,
230
+ pod_name=pod_name,
231
+ namespace=self.config.kubernetes_namespace,
232
+ exit_condition_lambda=kube_utils.pod_is_done,
233
+ stream_logs=True,
234
+ )
235
+ logger.info("Pod of step `%s` completed.", info.pipeline_step_name)
@@ -18,7 +18,7 @@ from uuid import UUID
18
18
 
19
19
  from pydantic import Field
20
20
 
21
- from zenml.config.source import Source
21
+ from zenml.config.source import Source, SourceWithValidator
22
22
  from zenml.constants import STR_FIELD_MAX_LENGTH, TEXT_FIELD_MAX_LENGTH
23
23
  from zenml.models.v2.base.base import BaseUpdate
24
24
  from zenml.models.v2.base.scoped import (
@@ -71,7 +71,7 @@ class CodeRepositoryUpdate(BaseUpdate):
71
71
  description="Configuration for the code repository.",
72
72
  default=None,
73
73
  )
74
- source: Optional[Source] = Field(
74
+ source: Optional[SourceWithValidator] = Field(
75
75
  description="The code repository source.", default=None
76
76
  )
77
77
  logo_url: Optional[str] = Field(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zenml-nightly
3
- Version: 0.62.0.dev20240726
3
+ Version: 0.62.0.dev20240727
4
4
  Summary: ZenML: Write production-ready ML code.
5
5
  Home-page: https://zenml.io
6
6
  License: Apache-2.0
@@ -6,7 +6,7 @@ RELEASE_NOTES.md,sha256=rF05H0U7U4lCYWomDqKhWdaWtOfCFSOf10LNBoFnl3Y,349994
6
6
  ROADMAP.md,sha256=hiLSmr16BH8Dfx7SaQM4JcXCGCVl6mFZPFAwJeDTrJU,407
7
7
  SECURITY.md,sha256=9DepA8y03yvCZLHEfcXLTDH4lUyKHquAdukBsccNN7c,682
8
8
  zenml/README.md,sha256=827dekbOWAs1BpW7VF1a4d7EbwPbjwccX-2zdXBENZo,1777
9
- zenml/VERSION,sha256=DMw9wlXKdcodfMglvAg9UJyL7xDqhHjHIFpqVlXkkpI,19
9
+ zenml/VERSION,sha256=MMNIds-xBnzHeYmjMTYM_s5WfrIGWKYS5QNBbYJrXeU,19
10
10
  zenml/__init__.py,sha256=6zRqB0FeBWX5E4Np9k9jzJgKaEHKvLFbtmOZQYrGpD8,2453
11
11
  zenml/_hub/__init__.py,sha256=6qDzpQAAZa__Aiiz0mC1qM-9dw9_jk_v_aXeJknxbDE,644
12
12
  zenml/_hub/client.py,sha256=Um2df1JO7-BmNm65efHSPpV5e0GITuoQJmod_wkdvbw,9136
@@ -84,7 +84,7 @@ zenml/config/docker_settings.py,sha256=3RxpPH53gX8_JPHvEUUlX-r-Q2E7DAiNNLYg5NLZD
84
84
  zenml/config/global_config.py,sha256=i1CY0d4T2C0iVqLGVSgTJ90vLQsCZyCGRodaZ73XTi8,29069
85
85
  zenml/config/pipeline_configurations.py,sha256=lqIShOr4Mha57dH-NOhSpemlTd3YafbXyR3FlQ6EVF0,2963
86
86
  zenml/config/pipeline_run_configuration.py,sha256=oEKmk55ARJU1JIaAy6agDnyAIwirXM5I-PksVAILtM8,1955
87
- zenml/config/pipeline_spec.py,sha256=-Vstse4d1IU0SAkMSiuDzFFeO6wzEI7bV8AtGogBWuI,2787
87
+ zenml/config/pipeline_spec.py,sha256=uWpiIfznJvXAiKs1yMIUDT1h1tYEFNO-RDVTYcIv9CE,2821
88
88
  zenml/config/resource_settings.py,sha256=bl3xahx--XS9p1CsTDSuvkZX9Oxb-Zj85UpefR8WrYs,3899
89
89
  zenml/config/retry_config.py,sha256=4UH1xqw0G6fSEbXSNKfmiFEkwadxQef9BGMe3JBm6NI,929
90
90
  zenml/config/schedule.py,sha256=QdezLjIONnEAVPrWFekbetNvkclx_5eJyhza0Prl5Y0,4944
@@ -93,7 +93,7 @@ zenml/config/secrets_store_config.py,sha256=y05zqyQhr_DGrs3IfBGa_FRoZ043hSYRT5wz
93
93
  zenml/config/server_config.py,sha256=0kM2xyikvXxLaNTKFHHU3xG-niHAjoI3n6uOgH3ntkw,23339
94
94
  zenml/config/settings_resolver.py,sha256=PR9BRm_x1dy7nVKa9UqpeFdck8IEATSW6aWT8FKd-DI,4278
95
95
  zenml/config/source.py,sha256=rm3kbtO4L_Yqcr01qrzid3Cquh_iqKkvIBTmdijqAAA,6808
96
- zenml/config/step_configurations.py,sha256=ZfiqFP2sl0d6hxMLro5AjmtEazWak8KgnFJkTnUXhbg,9650
96
+ zenml/config/step_configurations.py,sha256=TrPckVEgO7kyu9wL8PtL9eMIK_2TbbYvSBdE3ezUNTA,9689
97
97
  zenml/config/step_run_info.py,sha256=KiVRSTtKmZ1GbvseDTap2imr7XwMHD3jSFVpyLNEK1I,1888
98
98
  zenml/config/store_config.py,sha256=Cla5p5dTB6nNlo8_OZDs9hod5hspi64vxwtZj882XgU,3559
99
99
  zenml/config/strict_base_model.py,sha256=iHnO9qOmLUP_eiy9IjRr3JjIs1l1I_CsRQ76EyAneYU,860
@@ -268,7 +268,7 @@ zenml/integrations/gcp/google_credentials_mixin.py,sha256=bPy3JYCCcyuTmPiVFqbY81
268
268
  zenml/integrations/gcp/image_builders/__init__.py,sha256=2IvTL6U2YpUoxGQXeXew-6WFoL5hHIxkqr4DaA5Ez9w,786
269
269
  zenml/integrations/gcp/image_builders/gcp_image_builder.py,sha256=dNpMJa1TITUOHSn5nj1gWTFwVNmvWz321A_JoTMOqCM,9114
270
270
  zenml/integrations/gcp/orchestrators/__init__.py,sha256=6xLFJKZKQk73fHPF-XdpbQO87zjQNGTsNHjJjLfG_Kg,805
271
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py,sha256=m-CdecI_yCSWiuLBTvpx5ziU1BxlUD3T1sf31k55-Ks,29212
271
+ zenml/integrations/gcp/orchestrators/vertex_orchestrator.py,sha256=SDXZqKS7RHaBCqWZIf_1CVqtT4hhs9dfyT7nx4meKq4,30189
272
272
  zenml/integrations/gcp/service_connectors/__init__.py,sha256=fdydawaor8KAtMYvRZieiTuA1i5QATxXXgI-yV1lsn8,788
273
273
  zenml/integrations/gcp/service_connectors/gcp_service_connector.py,sha256=ouP62k-zm3vBf6_XoLopSnjfp0rEzu19yeax53cRMk0,89990
274
274
  zenml/integrations/gcp/step_operators/__init__.py,sha256=iPkob2LtPIQ-OHszhbNz_ojhoovL6SprmTx37It4EJ8,808
@@ -329,9 +329,10 @@ zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py,sha256=XRt1J
329
329
  zenml/integrations/kubeflow/orchestrators/__init__.py,sha256=J879DBt9WbpojBTdOXy7CO6F5OuTMntBeZ8aUY2EGO8,821
330
330
  zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py,sha256=AaAW5HqUeUDzqg_0Hk9SN_KFzEb0bLmD_woERIvRhDc,39165
331
331
  zenml/integrations/kubeflow/orchestrators/local_deployment_utils.py,sha256=qszoOdvBpgIp40XkncphXAr9dRKnyZzGiz2mJ56bYmw,15448
332
- zenml/integrations/kubernetes/__init__.py,sha256=MOR7sv65969FfA-uq5d6dtyjQfFxzcEHB40l-1NY324,1747
333
- zenml/integrations/kubernetes/flavors/__init__.py,sha256=ANKG2tCNpna3xVSmA2V9WOwFBgVX67V_ax-lGoVZ_So,966
332
+ zenml/integrations/kubernetes/__init__.py,sha256=UzU5CaogX6ud5ChCK8JSZ06eoW18eIudbgntgPijYSc,1853
333
+ zenml/integrations/kubernetes/flavors/__init__.py,sha256=a5gU45qCj3FkLwl_uVjlIkL_2F5DHk-w1gdcZrvVjBI,1266
334
334
  zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py,sha256=8SHSyXg0vPxTHsJhQ_MJpSLkDAAw-YvMNUQcvIn5ogo,7689
335
+ zenml/integrations/kubernetes/flavors/kubernetes_step_operator_flavor.py,sha256=ILN-H4cl7z3i4ltb4UBs55wbtIo871b4ib28pYkQoyQ,5605
335
336
  zenml/integrations/kubernetes/orchestrators/__init__.py,sha256=TJID3OTieZBox36WpQpzD0jdVRA_aZVcs_bNtfXS8ik,811
336
337
  zenml/integrations/kubernetes/orchestrators/kube_utils.py,sha256=o5yfxHt3hPGc6ki5Pzr_FRcUk-KNUh2PTxRUlVnUVCI,10639
337
338
  zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py,sha256=vuyHmaNwiVCPL7uN68HWa8gNmwNc0GH65NC48BfJgA8,20303
@@ -342,6 +343,8 @@ zenml/integrations/kubernetes/pod_settings.py,sha256=NMp4aHKRG29mh1Nq5uvV78Hzj1c
342
343
  zenml/integrations/kubernetes/serialization_utils.py,sha256=cPSe4szdBLzDnUZT9nQc2CCA8h84aj5oTA8vsUE36ig,7000
343
344
  zenml/integrations/kubernetes/service_connectors/__init__.py,sha256=Uf6zlHIapYrRDl3xOPWQ2jA7jt85SXx1U7DmSxzxTvQ,818
344
345
  zenml/integrations/kubernetes/service_connectors/kubernetes_service_connector.py,sha256=IbVWwKEXG7PZay1lj3Q1VNAlap4qGxjhE4yIW9_0tIc,19525
346
+ zenml/integrations/kubernetes/step_operators/__init__.py,sha256=40utDPYAezxHsFgO0UUIT_6XpCDzDapje6OH951XsTs,806
347
+ zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py,sha256=sEz8IZkzo0qarnPCr8zarBPHR0T0i6HL8r9nSNHQBxI,8310
345
348
  zenml/integrations/label_studio/__init__.py,sha256=tXmK0Wu_bFgtL7CqPPubSK99PaBZSyAu90aghHlXAek,1520
346
349
  zenml/integrations/label_studio/annotators/__init__.py,sha256=YtOtSfS1_NBoLoXIygEerElBP1-B98UU0HOAEfzdRY0,821
347
350
  zenml/integrations/label_studio/annotators/label_studio_annotator.py,sha256=VkuW4zsZhHz8__P9WTTLRTF-FOmoYB-_cFqBdu-PUyA,30498
@@ -585,7 +588,7 @@ zenml/models/v2/core/artifact.py,sha256=3MXZLTzTAOSMwdOmM-WhVERBx55ajhEd3xu2P-ru
585
588
  zenml/models/v2/core/artifact_version.py,sha256=kmMmYWnN6DO6jPWb-Ct89d0p9Vj4c32_7MG6dIqToPs,18256
586
589
  zenml/models/v2/core/artifact_visualization.py,sha256=milAHTpfuYd8Dx_oB4hcPYJL-TMoiU0FwUI0UhB3F-E,3115
587
590
  zenml/models/v2/core/code_reference.py,sha256=9xy3Gzychq16lLUs01va3gGfwdu-AMrFgys_ua89uFY,3557
588
- zenml/models/v2/core/code_repository.py,sha256=S_p-cC99g0IxwWc8ux1enveM6pXhkyKMF8sQiUnR7qc,5925
591
+ zenml/models/v2/core/code_repository.py,sha256=B3Ox9E_Zr9L1pd1CG_sO1h5dELsK-rDxjDoLfNmIgAs,5959
589
592
  zenml/models/v2/core/component.py,sha256=7isCreRBVolPxMp1VrkoNsyOA4LdSY5zMaXXVHbY_xo,13392
590
593
  zenml/models/v2/core/device.py,sha256=Vlz4-6VwglKL3F-k7DObH-2LeHc8oRqKbYxSImHvDJk,13929
591
594
  zenml/models/v2/core/event_source.py,sha256=kOexFvxj3iqsQGiGHPe549v9cSTo2GfsPCK05eDiNCw,6899
@@ -1337,8 +1340,8 @@ zenml/zen_stores/secrets_stores/service_connector_secrets_store.py,sha256=kPYX-Z
1337
1340
  zenml/zen_stores/secrets_stores/sql_secrets_store.py,sha256=Bq1djrUP9saoD7vECjS7-TlA_7sjJGgw1talri4spjU,8656
1338
1341
  zenml/zen_stores/sql_zen_store.py,sha256=j1D_vqLzg8lK2wT-a8moDOXJfTVGAa_oA0bb-RHWEVo,381780
1339
1342
  zenml/zen_stores/zen_store_interface.py,sha256=ZcgPtlAMdO5die42Hwd6l8glxHYsxFjzuCBewIu5Hrs,91984
1340
- zenml_nightly-0.62.0.dev20240726.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
1341
- zenml_nightly-0.62.0.dev20240726.dist-info/METADATA,sha256=HFoEEbqPZcjcSL0UXxx0jnKMpK53P_MzS_GnBrUP2YQ,21024
1342
- zenml_nightly-0.62.0.dev20240726.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1343
- zenml_nightly-0.62.0.dev20240726.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
1344
- zenml_nightly-0.62.0.dev20240726.dist-info/RECORD,,
1343
+ zenml_nightly-0.62.0.dev20240727.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
1344
+ zenml_nightly-0.62.0.dev20240727.dist-info/METADATA,sha256=hq-MK42ldYlEHXVW87J6rPHtcrcKqJ1c2fDo3eMbKPE,21024
1345
+ zenml_nightly-0.62.0.dev20240727.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1346
+ zenml_nightly-0.62.0.dev20240727.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
1347
+ zenml_nightly-0.62.0.dev20240727.dist-info/RECORD,,