zenml-nightly 0.70.0.dev20241203__py3-none-any.whl → 0.70.0.dev20241204__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 +1 -1
- zenml/image_builders/base_image_builder.py +5 -2
- zenml/image_builders/build_context.py +7 -16
- zenml/integrations/aws/__init__.py +3 -0
- zenml/integrations/aws/flavors/__init__.py +6 -0
- zenml/integrations/aws/flavors/aws_image_builder_flavor.py +146 -0
- zenml/integrations/aws/image_builders/__init__.py +20 -0
- zenml/integrations/aws/image_builders/aws_image_builder.py +307 -0
- zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +2 -1
- zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +11 -0
- zenml/integrations/lightning/flavors/lightning_orchestrator_flavor.py +11 -0
- zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +12 -0
- zenml/materializers/built_in_materializer.py +1 -1
- zenml/orchestrators/base_orchestrator.py +12 -0
- zenml/orchestrators/output_utils.py +5 -1
- zenml/service_connectors/service_connector_utils.py +3 -9
- zenml/stack_deployments/aws_stack_deployment.py +22 -0
- zenml/utils/archivable.py +65 -36
- zenml/utils/code_utils.py +8 -4
- zenml/utils/docker_utils.py +9 -0
- {zenml_nightly-0.70.0.dev20241203.dist-info → zenml_nightly-0.70.0.dev20241204.dist-info}/METADATA +1 -1
- {zenml_nightly-0.70.0.dev20241203.dist-info → zenml_nightly-0.70.0.dev20241204.dist-info}/RECORD +25 -22
- {zenml_nightly-0.70.0.dev20241203.dist-info → zenml_nightly-0.70.0.dev20241204.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.70.0.dev20241203.dist-info → zenml_nightly-0.70.0.dev20241204.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.70.0.dev20241203.dist-info → zenml_nightly-0.70.0.dev20241204.dist-info}/entry_points.txt +0 -0
zenml/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.70.0.
|
1
|
+
0.70.0.dev20241204
|
@@ -25,6 +25,7 @@ from zenml.io import fileio
|
|
25
25
|
from zenml.logger import get_logger
|
26
26
|
from zenml.stack import Flavor, StackComponent
|
27
27
|
from zenml.stack.stack_component import StackComponentConfig
|
28
|
+
from zenml.utils.archivable import ArchiveType
|
28
29
|
|
29
30
|
if TYPE_CHECKING:
|
30
31
|
from zenml.container_registries import BaseContainerRegistry
|
@@ -100,6 +101,7 @@ class BaseImageBuilder(StackComponent, ABC):
|
|
100
101
|
def _upload_build_context(
|
101
102
|
build_context: "BuildContext",
|
102
103
|
parent_path_directory_name: str,
|
104
|
+
archive_type: ArchiveType = ArchiveType.TAR_GZ,
|
103
105
|
) -> str:
|
104
106
|
"""Uploads a Docker image build context to a remote location.
|
105
107
|
|
@@ -109,6 +111,7 @@ class BaseImageBuilder(StackComponent, ABC):
|
|
109
111
|
the build context to. It will be appended to the artifact
|
110
112
|
store path to create the parent path where the build context
|
111
113
|
will be uploaded to.
|
114
|
+
archive_type: The type of archive to create.
|
112
115
|
|
113
116
|
Returns:
|
114
117
|
The path to the uploaded build context.
|
@@ -119,7 +122,7 @@ class BaseImageBuilder(StackComponent, ABC):
|
|
119
122
|
|
120
123
|
hash_ = hashlib.sha1() # nosec
|
121
124
|
with tempfile.NamedTemporaryFile(mode="w+b", delete=False) as f:
|
122
|
-
build_context.write_archive(f,
|
125
|
+
build_context.write_archive(f, archive_type)
|
123
126
|
|
124
127
|
while True:
|
125
128
|
data = f.read(64 * 1024)
|
@@ -127,7 +130,7 @@ class BaseImageBuilder(StackComponent, ABC):
|
|
127
130
|
break
|
128
131
|
hash_.update(data)
|
129
132
|
|
130
|
-
filename = f"{hash_.hexdigest()}.
|
133
|
+
filename = f"{hash_.hexdigest()}.{archive_type.value}"
|
131
134
|
filepath = f"{parent_path}/{filename}"
|
132
135
|
if not fileio.exists(filepath):
|
133
136
|
logger.info("Uploading build context to `%s`.", filepath)
|
@@ -20,7 +20,7 @@ from zenml.constants import REPOSITORY_DIRECTORY_NAME
|
|
20
20
|
from zenml.io import fileio
|
21
21
|
from zenml.logger import get_logger
|
22
22
|
from zenml.utils import io_utils, string_utils
|
23
|
-
from zenml.utils.archivable import Archivable
|
23
|
+
from zenml.utils.archivable import Archivable, ArchiveType
|
24
24
|
|
25
25
|
logger = get_logger(__name__)
|
26
26
|
|
@@ -69,28 +69,19 @@ class BuildContext(Archivable):
|
|
69
69
|
return None
|
70
70
|
|
71
71
|
def write_archive(
|
72
|
-
self,
|
72
|
+
self,
|
73
|
+
output_file: IO[bytes],
|
74
|
+
archive_type: ArchiveType = ArchiveType.TAR_GZ,
|
73
75
|
) -> None:
|
74
76
|
"""Writes an archive of the build context to the given file.
|
75
77
|
|
76
78
|
Args:
|
77
79
|
output_file: The file to write the archive to.
|
78
|
-
|
80
|
+
archive_type: The type of archive to create.
|
79
81
|
"""
|
80
|
-
|
81
|
-
|
82
|
-
files = self.get_files()
|
83
|
-
extra_files = self.get_extra_files()
|
84
|
-
|
85
|
-
context_archive = docker_build_utils.create_archive(
|
86
|
-
fileobj=output_file,
|
87
|
-
root=self._root,
|
88
|
-
files=sorted(files.keys()),
|
89
|
-
gzip=use_gzip,
|
90
|
-
extra_files=list(extra_files.items()),
|
91
|
-
)
|
82
|
+
super().write_archive(output_file, archive_type)
|
92
83
|
|
93
|
-
build_context_size = os.path.getsize(
|
84
|
+
build_context_size = os.path.getsize(output_file.name)
|
94
85
|
if (
|
95
86
|
self._root
|
96
87
|
and build_context_size > 50 * 1024 * 1024
|
@@ -33,6 +33,7 @@ AWS_SAGEMAKER_ORCHESTRATOR_FLAVOR = "sagemaker"
|
|
33
33
|
AWS_CONNECTOR_TYPE = "aws"
|
34
34
|
AWS_RESOURCE_TYPE = "aws-generic"
|
35
35
|
S3_RESOURCE_TYPE = "s3-bucket"
|
36
|
+
AWS_IMAGE_BUILDER_FLAVOR = "aws"
|
36
37
|
|
37
38
|
class AWSIntegration(Integration):
|
38
39
|
"""Definition of AWS integration for ZenML."""
|
@@ -59,12 +60,14 @@ class AWSIntegration(Integration):
|
|
59
60
|
"""
|
60
61
|
from zenml.integrations.aws.flavors import (
|
61
62
|
AWSContainerRegistryFlavor,
|
63
|
+
AWSImageBuilderFlavor,
|
62
64
|
SagemakerOrchestratorFlavor,
|
63
65
|
SagemakerStepOperatorFlavor,
|
64
66
|
)
|
65
67
|
|
66
68
|
return [
|
67
69
|
AWSContainerRegistryFlavor,
|
70
|
+
AWSImageBuilderFlavor,
|
68
71
|
SagemakerStepOperatorFlavor,
|
69
72
|
SagemakerOrchestratorFlavor,
|
70
73
|
]
|
@@ -17,6 +17,10 @@ from zenml.integrations.aws.flavors.aws_container_registry_flavor import (
|
|
17
17
|
AWSContainerRegistryConfig,
|
18
18
|
AWSContainerRegistryFlavor,
|
19
19
|
)
|
20
|
+
from zenml.integrations.aws.flavors.aws_image_builder_flavor import (
|
21
|
+
AWSImageBuilderConfig,
|
22
|
+
AWSImageBuilderFlavor,
|
23
|
+
)
|
20
24
|
from zenml.integrations.aws.flavors.sagemaker_orchestrator_flavor import (
|
21
25
|
SagemakerOrchestratorConfig,
|
22
26
|
SagemakerOrchestratorFlavor,
|
@@ -29,6 +33,8 @@ from zenml.integrations.aws.flavors.sagemaker_step_operator_flavor import (
|
|
29
33
|
__all__ = [
|
30
34
|
"AWSContainerRegistryFlavor",
|
31
35
|
"AWSContainerRegistryConfig",
|
36
|
+
"AWSImageBuilderConfig",
|
37
|
+
"AWSImageBuilderFlavor",
|
32
38
|
"SagemakerStepOperatorFlavor",
|
33
39
|
"SagemakerStepOperatorConfig",
|
34
40
|
"SagemakerOrchestratorFlavor",
|
@@ -0,0 +1,146 @@
|
|
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
|
+
"""AWS Code Build image builder flavor."""
|
15
|
+
|
16
|
+
from typing import TYPE_CHECKING, Dict, Optional, Type
|
17
|
+
|
18
|
+
from zenml.image_builders import BaseImageBuilderConfig, BaseImageBuilderFlavor
|
19
|
+
from zenml.integrations.aws import (
|
20
|
+
AWS_CONNECTOR_TYPE,
|
21
|
+
AWS_IMAGE_BUILDER_FLAVOR,
|
22
|
+
AWS_RESOURCE_TYPE,
|
23
|
+
)
|
24
|
+
from zenml.models import ServiceConnectorRequirements
|
25
|
+
|
26
|
+
if TYPE_CHECKING:
|
27
|
+
from zenml.integrations.aws.image_builders import AWSImageBuilder
|
28
|
+
|
29
|
+
|
30
|
+
DEFAULT_CLOUDBUILD_IMAGE = "bentolor/docker-dind-awscli"
|
31
|
+
DEFAULT_CLOUDBUILD_COMPUTE_TYPE = "BUILD_GENERAL1_SMALL"
|
32
|
+
|
33
|
+
|
34
|
+
class AWSImageBuilderConfig(BaseImageBuilderConfig):
|
35
|
+
"""AWS Code Build image builder configuration.
|
36
|
+
|
37
|
+
Attributes:
|
38
|
+
code_build_project: The name of an existing AWS CodeBuild project to use
|
39
|
+
to build the image. The CodeBuild project must exist in the AWS
|
40
|
+
account and region inferred from the AWS service connector
|
41
|
+
credentials or implicitly from the local AWS config.
|
42
|
+
build_image: The Docker image to use for the AWS CodeBuild environment.
|
43
|
+
The image must have Docker installed and be able to run Docker
|
44
|
+
commands. The default image is bentolor/docker-dind-awscli.
|
45
|
+
This can be customized to use a mirror, if needed, in case the
|
46
|
+
Dockerhub image is not accessible or rate-limited.
|
47
|
+
custom_env_vars: Custom environment variables to pass to the AWS
|
48
|
+
CodeBuild build.
|
49
|
+
compute_type: The compute type to use for the AWS CodeBuild build.
|
50
|
+
The default is BUILD_GENERAL1_SMALL.
|
51
|
+
implicit_container_registry_auth: Whether to use implicit authentication
|
52
|
+
to authenticate the AWS Code Build build to the container registry
|
53
|
+
when pushing container images. If set to False, the container
|
54
|
+
registry credentials must be explicitly configured for the container
|
55
|
+
registry stack component or the container registry stack component
|
56
|
+
must be linked to a service connector.
|
57
|
+
NOTE: When implicit_container_registry_auth is set to False, the
|
58
|
+
container registry credentials will be passed to the AWS Code Build
|
59
|
+
build as environment variables. This is not recommended for
|
60
|
+
production use unless your service connector is configured to
|
61
|
+
generate short-lived credentials.
|
62
|
+
"""
|
63
|
+
|
64
|
+
code_build_project: str
|
65
|
+
build_image: str = DEFAULT_CLOUDBUILD_IMAGE
|
66
|
+
custom_env_vars: Optional[Dict[str, str]] = None
|
67
|
+
compute_type: str = DEFAULT_CLOUDBUILD_COMPUTE_TYPE
|
68
|
+
implicit_container_registry_auth: bool = True
|
69
|
+
|
70
|
+
|
71
|
+
class AWSImageBuilderFlavor(BaseImageBuilderFlavor):
|
72
|
+
"""AWS Code Build image builder flavor."""
|
73
|
+
|
74
|
+
@property
|
75
|
+
def name(self) -> str:
|
76
|
+
"""The flavor name.
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
The name of the flavor.
|
80
|
+
"""
|
81
|
+
return AWS_IMAGE_BUILDER_FLAVOR
|
82
|
+
|
83
|
+
@property
|
84
|
+
def service_connector_requirements(
|
85
|
+
self,
|
86
|
+
) -> Optional[ServiceConnectorRequirements]:
|
87
|
+
"""Service connector resource requirements for service connectors.
|
88
|
+
|
89
|
+
Specifies resource requirements that are used to filter the available
|
90
|
+
service connector types that are compatible with this flavor.
|
91
|
+
|
92
|
+
Returns:
|
93
|
+
Requirements for compatible service connectors, if a service
|
94
|
+
connector is required for this flavor.
|
95
|
+
"""
|
96
|
+
return ServiceConnectorRequirements(
|
97
|
+
connector_type=AWS_CONNECTOR_TYPE,
|
98
|
+
resource_type=AWS_RESOURCE_TYPE,
|
99
|
+
)
|
100
|
+
|
101
|
+
@property
|
102
|
+
def docs_url(self) -> Optional[str]:
|
103
|
+
"""A url to point at docs explaining this flavor.
|
104
|
+
|
105
|
+
Returns:
|
106
|
+
A flavor docs url.
|
107
|
+
"""
|
108
|
+
return self.generate_default_docs_url()
|
109
|
+
|
110
|
+
@property
|
111
|
+
def sdk_docs_url(self) -> Optional[str]:
|
112
|
+
"""A url to point at SDK docs explaining this flavor.
|
113
|
+
|
114
|
+
Returns:
|
115
|
+
A flavor SDK docs url.
|
116
|
+
"""
|
117
|
+
return self.generate_default_sdk_docs_url()
|
118
|
+
|
119
|
+
@property
|
120
|
+
def logo_url(self) -> str:
|
121
|
+
"""A url to represent the flavor in the dashboard.
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
The flavor logo.
|
125
|
+
"""
|
126
|
+
return "https://public-flavor-logos.s3.eu-central-1.amazonaws.com/image_builder/aws.png"
|
127
|
+
|
128
|
+
@property
|
129
|
+
def config_class(self) -> Type[BaseImageBuilderConfig]:
|
130
|
+
"""The config class.
|
131
|
+
|
132
|
+
Returns:
|
133
|
+
The config class.
|
134
|
+
"""
|
135
|
+
return AWSImageBuilderConfig
|
136
|
+
|
137
|
+
@property
|
138
|
+
def implementation_class(self) -> Type["AWSImageBuilder"]:
|
139
|
+
"""Implementation class.
|
140
|
+
|
141
|
+
Returns:
|
142
|
+
The implementation class.
|
143
|
+
"""
|
144
|
+
from zenml.integrations.aws.image_builders import AWSImageBuilder
|
145
|
+
|
146
|
+
return AWSImageBuilder
|
@@ -0,0 +1,20 @@
|
|
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
|
+
"""Initialization for the AWS image builder."""
|
15
|
+
|
16
|
+
from zenml.integrations.aws.image_builders.aws_image_builder import (
|
17
|
+
AWSImageBuilder,
|
18
|
+
)
|
19
|
+
|
20
|
+
__all__ = ["AWSImageBuilder"]
|
@@ -0,0 +1,307 @@
|
|
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
|
+
"""AWS Code Build image builder implementation."""
|
15
|
+
|
16
|
+
import time
|
17
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, cast
|
18
|
+
from urllib.parse import urlparse
|
19
|
+
from uuid import uuid4
|
20
|
+
|
21
|
+
import boto3
|
22
|
+
|
23
|
+
from zenml.enums import StackComponentType
|
24
|
+
from zenml.image_builders import BaseImageBuilder
|
25
|
+
from zenml.integrations.aws import (
|
26
|
+
AWS_CONTAINER_REGISTRY_FLAVOR,
|
27
|
+
)
|
28
|
+
from zenml.integrations.aws.flavors import AWSImageBuilderConfig
|
29
|
+
from zenml.logger import get_logger
|
30
|
+
from zenml.stack import StackValidator
|
31
|
+
from zenml.utils.archivable import ArchiveType
|
32
|
+
|
33
|
+
if TYPE_CHECKING:
|
34
|
+
from zenml.container_registries import BaseContainerRegistry
|
35
|
+
from zenml.image_builders import BuildContext
|
36
|
+
from zenml.stack import Stack
|
37
|
+
|
38
|
+
logger = get_logger(__name__)
|
39
|
+
|
40
|
+
|
41
|
+
class AWSImageBuilder(BaseImageBuilder):
|
42
|
+
"""AWS Code Build image builder implementation."""
|
43
|
+
|
44
|
+
_code_build_client: Optional[Any] = None
|
45
|
+
|
46
|
+
@property
|
47
|
+
def config(self) -> AWSImageBuilderConfig:
|
48
|
+
"""The stack component configuration.
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
The configuration.
|
52
|
+
"""
|
53
|
+
return cast(AWSImageBuilderConfig, self._config)
|
54
|
+
|
55
|
+
@property
|
56
|
+
def is_building_locally(self) -> bool:
|
57
|
+
"""Whether the image builder builds the images on the client machine.
|
58
|
+
|
59
|
+
Returns:
|
60
|
+
True if the image builder builds locally, False otherwise.
|
61
|
+
"""
|
62
|
+
return False
|
63
|
+
|
64
|
+
@property
|
65
|
+
def validator(self) -> Optional["StackValidator"]:
|
66
|
+
"""Validates the stack for the AWS Code Build Image Builder.
|
67
|
+
|
68
|
+
The AWS Code Build Image Builder requires a container registry to
|
69
|
+
push the image to and an S3 Artifact Store to upload the build context,
|
70
|
+
so AWS Code Build can access it.
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
Stack validator.
|
74
|
+
"""
|
75
|
+
|
76
|
+
def _validate_remote_components(stack: "Stack") -> Tuple[bool, str]:
|
77
|
+
if stack.artifact_store.flavor != "s3":
|
78
|
+
return False, (
|
79
|
+
"The AWS Image Builder requires an S3 Artifact Store to "
|
80
|
+
"upload the build context, so AWS Code Build can access it."
|
81
|
+
"Please update your stack to include an S3 Artifact Store "
|
82
|
+
"and try again."
|
83
|
+
)
|
84
|
+
|
85
|
+
return True, ""
|
86
|
+
|
87
|
+
return StackValidator(
|
88
|
+
required_components={StackComponentType.CONTAINER_REGISTRY},
|
89
|
+
custom_validation_function=_validate_remote_components,
|
90
|
+
)
|
91
|
+
|
92
|
+
@property
|
93
|
+
def code_build_client(self) -> Any:
|
94
|
+
"""The authenticated AWS Code Build client to use for interacting with AWS services.
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
The authenticated AWS Code Build client.
|
98
|
+
|
99
|
+
Raises:
|
100
|
+
RuntimeError: If the AWS Code Build client cannot be created.
|
101
|
+
"""
|
102
|
+
if (
|
103
|
+
self._code_build_client is not None
|
104
|
+
and self.connector_has_expired()
|
105
|
+
):
|
106
|
+
self._code_build_client = None
|
107
|
+
if self._code_build_client is not None:
|
108
|
+
return self._code_build_client
|
109
|
+
|
110
|
+
# Option 1: Service connector
|
111
|
+
if connector := self.get_connector():
|
112
|
+
boto_session = connector.connect()
|
113
|
+
if not isinstance(boto_session, boto3.Session):
|
114
|
+
raise RuntimeError(
|
115
|
+
f"Expected to receive a `boto3.Session` object from the "
|
116
|
+
f"linked connector, but got type `{type(boto_session)}`."
|
117
|
+
)
|
118
|
+
# Option 2: Implicit configuration
|
119
|
+
else:
|
120
|
+
boto_session = boto3.Session()
|
121
|
+
|
122
|
+
self._code_build_client = boto_session.client("codebuild")
|
123
|
+
return self._code_build_client
|
124
|
+
|
125
|
+
def build(
|
126
|
+
self,
|
127
|
+
image_name: str,
|
128
|
+
build_context: "BuildContext",
|
129
|
+
docker_build_options: Dict[str, Any],
|
130
|
+
container_registry: Optional["BaseContainerRegistry"] = None,
|
131
|
+
) -> str:
|
132
|
+
"""Builds and pushes a Docker image.
|
133
|
+
|
134
|
+
Args:
|
135
|
+
image_name: Name of the image to build and push.
|
136
|
+
build_context: The build context to use for the image.
|
137
|
+
docker_build_options: Docker build options.
|
138
|
+
container_registry: Optional container registry to push to.
|
139
|
+
|
140
|
+
Returns:
|
141
|
+
The Docker image name with digest.
|
142
|
+
|
143
|
+
Raises:
|
144
|
+
RuntimeError: If no container registry is passed.
|
145
|
+
RuntimeError: If the Cloud Build build fails.
|
146
|
+
"""
|
147
|
+
if not container_registry:
|
148
|
+
raise RuntimeError(
|
149
|
+
"The AWS Image Builder requires a container registry to push "
|
150
|
+
"the image to. Please provide one and try again."
|
151
|
+
)
|
152
|
+
|
153
|
+
logger.info("Using AWS Code Build to build image `%s`", image_name)
|
154
|
+
cloud_build_context = self._upload_build_context(
|
155
|
+
build_context=build_context,
|
156
|
+
parent_path_directory_name=f"code-build-contexts/{str(self.id)}",
|
157
|
+
archive_type=ArchiveType.ZIP,
|
158
|
+
)
|
159
|
+
|
160
|
+
url_parts = urlparse(cloud_build_context)
|
161
|
+
bucket = url_parts.netloc
|
162
|
+
object_path = url_parts.path.lstrip("/")
|
163
|
+
logger.info(
|
164
|
+
"Build context located in bucket `%s` and object path `%s`",
|
165
|
+
bucket,
|
166
|
+
object_path,
|
167
|
+
)
|
168
|
+
|
169
|
+
# Pass authentication credentials as environment variables, if
|
170
|
+
# the container registry has credentials and if implicit authentication
|
171
|
+
# is disabled
|
172
|
+
environment_variables_override: Dict[str, str] = {}
|
173
|
+
pre_build_commands = []
|
174
|
+
if not self.config.implicit_container_registry_auth:
|
175
|
+
credentials = container_registry.credentials
|
176
|
+
if credentials:
|
177
|
+
environment_variables_override = {
|
178
|
+
"CONTAINER_REGISTRY_USERNAME": credentials[0],
|
179
|
+
"CONTAINER_REGISTRY_PASSWORD": credentials[1],
|
180
|
+
}
|
181
|
+
pre_build_commands = [
|
182
|
+
"echo Logging in to container registry",
|
183
|
+
'echo "$CONTAINER_REGISTRY_PASSWORD" | docker login --username "$CONTAINER_REGISTRY_USERNAME" --password-stdin '
|
184
|
+
f"{container_registry.config.uri}",
|
185
|
+
]
|
186
|
+
elif container_registry.flavor == AWS_CONTAINER_REGISTRY_FLAVOR:
|
187
|
+
pre_build_commands = [
|
188
|
+
"echo Logging in to EKS",
|
189
|
+
f"aws ecr get-login-password --region {self.code_build_client._client_config.region_name} | docker login --username AWS --password-stdin {container_registry.config.uri}",
|
190
|
+
]
|
191
|
+
|
192
|
+
# Convert the docker_build_options dictionary to a list of strings
|
193
|
+
docker_build_args = ""
|
194
|
+
for key, value in docker_build_options.items():
|
195
|
+
option = f"--{key}"
|
196
|
+
if isinstance(value, list):
|
197
|
+
for val in value:
|
198
|
+
docker_build_args += f"{option} {val} "
|
199
|
+
elif value is not None and not isinstance(value, bool):
|
200
|
+
docker_build_args += f"{option} {value} "
|
201
|
+
elif value is not False:
|
202
|
+
docker_build_args += f"{option} "
|
203
|
+
|
204
|
+
pre_build_commands_str = "\n".join(
|
205
|
+
[f" - {command}" for command in pre_build_commands]
|
206
|
+
)
|
207
|
+
|
208
|
+
# Generate and use a unique tag for the Docker image. This is easier
|
209
|
+
# than trying to parse the image digest from the Code Build logs.
|
210
|
+
build_id = str(uuid4())
|
211
|
+
# Replace the tag in the image name with the unique build ID
|
212
|
+
repo_name = image_name.split(":")[0]
|
213
|
+
alt_image_name = f"{repo_name}:{build_id}"
|
214
|
+
|
215
|
+
buildspec = f"""
|
216
|
+
version: 0.2
|
217
|
+
phases:
|
218
|
+
pre_build:
|
219
|
+
commands:
|
220
|
+
{pre_build_commands_str}
|
221
|
+
build:
|
222
|
+
commands:
|
223
|
+
- echo Build started on `date`
|
224
|
+
- echo Building the Docker image...
|
225
|
+
- docker build -t {image_name} . {docker_build_args}
|
226
|
+
- echo Build completed on `date`
|
227
|
+
post_build:
|
228
|
+
commands:
|
229
|
+
- echo Pushing the Docker image...
|
230
|
+
- docker push {image_name}
|
231
|
+
- docker tag {image_name} {alt_image_name}
|
232
|
+
- docker push {alt_image_name}
|
233
|
+
- echo Pushed the Docker image
|
234
|
+
artifacts:
|
235
|
+
files:
|
236
|
+
- '**/*'
|
237
|
+
"""
|
238
|
+
|
239
|
+
if self.config.custom_env_vars:
|
240
|
+
environment_variables_override.update(self.config.custom_env_vars)
|
241
|
+
|
242
|
+
environment_variables_override_list = [
|
243
|
+
{
|
244
|
+
"name": key,
|
245
|
+
"value": value,
|
246
|
+
"type": "PLAINTEXT",
|
247
|
+
}
|
248
|
+
for key, value in environment_variables_override.items()
|
249
|
+
]
|
250
|
+
|
251
|
+
# Override the build project with the parameters needed to run a
|
252
|
+
# docker-in-docker build, as covered here: https://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker-section.html
|
253
|
+
response = self.code_build_client.start_build(
|
254
|
+
projectName=self.config.code_build_project,
|
255
|
+
environmentTypeOverride="LINUX_CONTAINER",
|
256
|
+
imageOverride=self.config.build_image,
|
257
|
+
computeTypeOverride=self.config.compute_type,
|
258
|
+
privilegedModeOverride=False,
|
259
|
+
sourceTypeOverride="S3",
|
260
|
+
sourceLocationOverride=f"{bucket}/{object_path}",
|
261
|
+
buildspecOverride=buildspec,
|
262
|
+
environmentVariablesOverride=environment_variables_override_list,
|
263
|
+
# no artifacts
|
264
|
+
artifactsOverride={"type": "NO_ARTIFACTS"},
|
265
|
+
)
|
266
|
+
|
267
|
+
build_arn = response["build"]["arn"]
|
268
|
+
|
269
|
+
# Parse the AWS region, account, codebuild project and build name from the ARN
|
270
|
+
aws_region, aws_account, build = build_arn.split(":", maxsplit=5)[3:6]
|
271
|
+
codebuild_project = build.split("/")[1].split(":")[0]
|
272
|
+
|
273
|
+
logs_url = f"https://{aws_region}.console.aws.amazon.com/codesuite/codebuild/{aws_account}/projects/{codebuild_project}/{build}/log"
|
274
|
+
logger.info(
|
275
|
+
f"Running Code Build to build the Docker image. Cloud Build logs: `{logs_url}`",
|
276
|
+
)
|
277
|
+
|
278
|
+
# Wait for the build to complete
|
279
|
+
code_build_id = response["build"]["id"]
|
280
|
+
while True:
|
281
|
+
build_status = self.code_build_client.batch_get_builds(
|
282
|
+
ids=[code_build_id]
|
283
|
+
)
|
284
|
+
build = build_status["builds"][0]
|
285
|
+
status = build["buildStatus"]
|
286
|
+
if status in [
|
287
|
+
"SUCCEEDED",
|
288
|
+
"FAILED",
|
289
|
+
"FAULT",
|
290
|
+
"TIMED_OUT",
|
291
|
+
"STOPPED",
|
292
|
+
]:
|
293
|
+
break
|
294
|
+
time.sleep(10)
|
295
|
+
|
296
|
+
if status != "SUCCEEDED":
|
297
|
+
raise RuntimeError(
|
298
|
+
f"The Code Build run to build the Docker image has failed. More "
|
299
|
+
f"information can be found in the Cloud Build logs: {logs_url}."
|
300
|
+
)
|
301
|
+
|
302
|
+
logger.info(
|
303
|
+
f"The Docker image has been built successfully. More information can "
|
304
|
+
f"be found in the Cloud Build logs: `{logs_url}`."
|
305
|
+
)
|
306
|
+
|
307
|
+
return alt_image_name
|
@@ -25,6 +25,7 @@ from zenml.image_builders import BaseImageBuilder
|
|
25
25
|
from zenml.integrations.kaniko.flavors import KanikoImageBuilderConfig
|
26
26
|
from zenml.logger import get_logger
|
27
27
|
from zenml.stack import StackValidator
|
28
|
+
from zenml.utils.archivable import ArchiveType
|
28
29
|
|
29
30
|
if TYPE_CHECKING:
|
30
31
|
from zenml.container_registries import BaseContainerRegistry
|
@@ -295,7 +296,7 @@ class KanikoImageBuilder(BaseImageBuilder):
|
|
295
296
|
logger.debug("Writing build context to process stdin.")
|
296
297
|
assert process.stdin
|
297
298
|
with process.stdin as _, tempfile.TemporaryFile(mode="w+b") as f:
|
298
|
-
build_context.write_archive(f,
|
299
|
+
build_context.write_archive(f, archive_type=ArchiveType.TAR_GZ)
|
299
300
|
while True:
|
300
301
|
data = f.read(1024)
|
301
302
|
if not data:
|
@@ -134,6 +134,17 @@ class KubernetesOrchestratorConfig(
|
|
134
134
|
"""
|
135
135
|
return True
|
136
136
|
|
137
|
+
@property
|
138
|
+
def supports_client_side_caching(self) -> bool:
|
139
|
+
"""Whether the orchestrator supports client side caching.
|
140
|
+
|
141
|
+
Returns:
|
142
|
+
Whether the orchestrator supports client side caching.
|
143
|
+
"""
|
144
|
+
# The Kubernetes orchestrator starts step pods from a pipeline pod.
|
145
|
+
# This is currently not supported when using client-side caching.
|
146
|
+
return False
|
147
|
+
|
137
148
|
|
138
149
|
class KubernetesOrchestratorFlavor(BaseOrchestratorFlavor):
|
139
150
|
"""Kubernetes orchestrator flavor."""
|
@@ -94,6 +94,17 @@ class LightningOrchestratorConfig(
|
|
94
94
|
"""
|
95
95
|
return False
|
96
96
|
|
97
|
+
@property
|
98
|
+
def supports_client_side_caching(self) -> bool:
|
99
|
+
"""Whether the orchestrator supports client side caching.
|
100
|
+
|
101
|
+
Returns:
|
102
|
+
Whether the orchestrator supports client side caching.
|
103
|
+
"""
|
104
|
+
# The Lightning orchestrator starts step studios from a pipeline studio.
|
105
|
+
# This is currently not supported when using client-side caching.
|
106
|
+
return False
|
107
|
+
|
97
108
|
|
98
109
|
class LightningOrchestratorFlavor(BaseOrchestratorFlavor):
|
99
110
|
"""Lightning orchestrator flavor."""
|
@@ -144,3 +144,15 @@ class SkypilotBaseOrchestratorConfig(
|
|
144
144
|
True if this config is for a local component, False otherwise.
|
145
145
|
"""
|
146
146
|
return False
|
147
|
+
|
148
|
+
@property
|
149
|
+
def supports_client_side_caching(self) -> bool:
|
150
|
+
"""Whether the orchestrator supports client side caching.
|
151
|
+
|
152
|
+
Returns:
|
153
|
+
Whether the orchestrator supports client side caching.
|
154
|
+
"""
|
155
|
+
# The Skypilot orchestrator runs the entire pipeline in a single VM, or
|
156
|
+
# starts additional VMs from the root VM. Both of those cases are
|
157
|
+
# currently not supported when using client-side caching.
|
158
|
+
return False
|
@@ -429,7 +429,7 @@ class BuiltInContainerMaterializer(BaseMaterializer):
|
|
429
429
|
# doesn't work for non-serializable types as they
|
430
430
|
# are saved as list of lists in different files
|
431
431
|
if _is_serializable(data):
|
432
|
-
return {self.data_path: VisualizationType.JSON}
|
432
|
+
return {self.data_path.replace("\\", "/"): VisualizationType.JSON}
|
433
433
|
return {}
|
434
434
|
|
435
435
|
def extract_metadata(self, data: Any) -> Dict[str, "MetadataType"]:
|
@@ -84,6 +84,15 @@ class BaseOrchestratorConfig(StackComponentConfig):
|
|
84
84
|
"""
|
85
85
|
return False
|
86
86
|
|
87
|
+
@property
|
88
|
+
def supports_client_side_caching(self) -> bool:
|
89
|
+
"""Whether the orchestrator supports client side caching.
|
90
|
+
|
91
|
+
Returns:
|
92
|
+
Whether the orchestrator supports client side caching.
|
93
|
+
"""
|
94
|
+
return True
|
95
|
+
|
87
96
|
|
88
97
|
class BaseOrchestrator(StackComponent, ABC):
|
89
98
|
"""Base class for all orchestrators.
|
@@ -205,6 +214,7 @@ class BaseOrchestrator(StackComponent, ABC):
|
|
205
214
|
|
206
215
|
if (
|
207
216
|
placeholder_run
|
217
|
+
and self.config.supports_client_side_caching
|
208
218
|
and not deployment.schedule
|
209
219
|
and not prevent_client_side_caching
|
210
220
|
):
|
@@ -232,6 +242,8 @@ class BaseOrchestrator(StackComponent, ABC):
|
|
232
242
|
self._cleanup_run()
|
233
243
|
logger.info("All steps of the pipeline run were cached.")
|
234
244
|
return
|
245
|
+
else:
|
246
|
+
logger.debug("Skipping client-side caching.")
|
235
247
|
|
236
248
|
try:
|
237
249
|
if metadata_iterator := self.prepare_or_run_pipeline(
|
@@ -19,6 +19,7 @@ from uuid import uuid4
|
|
19
19
|
|
20
20
|
from zenml.client import Client
|
21
21
|
from zenml.logger import get_logger
|
22
|
+
from zenml.utils import string_utils
|
22
23
|
|
23
24
|
if TYPE_CHECKING:
|
24
25
|
from zenml.artifact_stores import BaseArtifactStore
|
@@ -75,10 +76,13 @@ def prepare_output_artifact_uris(
|
|
75
76
|
artifact_store = stack.artifact_store
|
76
77
|
output_artifact_uris: Dict[str, str] = {}
|
77
78
|
for output_name in step.config.outputs.keys():
|
79
|
+
substituted_output_name = string_utils.format_name_template(
|
80
|
+
output_name, substitutions=step_run.config.substitutions
|
81
|
+
)
|
78
82
|
artifact_uri = generate_artifact_uri(
|
79
83
|
artifact_store=stack.artifact_store,
|
80
84
|
step_run=step_run,
|
81
|
-
output_name=
|
85
|
+
output_name=substituted_output_name,
|
82
86
|
)
|
83
87
|
if artifact_store.exists(artifact_uri):
|
84
88
|
raise RuntimeError("Artifact already exists")
|
@@ -60,15 +60,9 @@ def _raise_specific_cloud_exception_if_needed(
|
|
60
60
|
orchestrators: List[ResourcesInfo],
|
61
61
|
container_registries: List[ResourcesInfo],
|
62
62
|
) -> None:
|
63
|
-
AWS_DOCS =
|
64
|
-
|
65
|
-
|
66
|
-
GCP_DOCS = (
|
67
|
-
"https://docs.zenml.io/how-to/infrastructure-deployment/auth-management/gcp-service-connector"
|
68
|
-
)
|
69
|
-
AZURE_DOCS = (
|
70
|
-
"https://docs.zenml.io/how-to/infrastructure-deployment/auth-management/azure-service-connector"
|
71
|
-
)
|
63
|
+
AWS_DOCS = "https://docs.zenml.io/how-to/infrastructure-deployment/auth-management/aws-service-connector"
|
64
|
+
GCP_DOCS = "https://docs.zenml.io/how-to/infrastructure-deployment/auth-management/gcp-service-connector"
|
65
|
+
AZURE_DOCS = "https://docs.zenml.io/how-to/infrastructure-deployment/auth-management/azure-service-connector"
|
72
66
|
|
73
67
|
if not artifact_stores:
|
74
68
|
error_msg = (
|
@@ -73,6 +73,7 @@ of any potential costs:
|
|
73
73
|
- An ECR repository registered as a [ZenML container registry](https://docs.zenml.io/stack-components/container-registries/aws).
|
74
74
|
- Sagemaker registered as a [ZenML orchestrator](https://docs.zenml.io/stack-components/orchestrators/sagemaker)
|
75
75
|
as well as a [ZenML step operator](https://docs.zenml.io/stack-components/step-operators/sagemaker).
|
76
|
+
- A CodeBuild project registered as a [ZenML image builder](https://docs.zenml.io/stack-components/image-builder/aws).
|
76
77
|
- An IAM user and IAM role with the minimum necessary permissions to access the
|
77
78
|
above resources.
|
78
79
|
- An AWS access key used to give access to ZenML to connect to the above
|
@@ -158,6 +159,26 @@ console.
|
|
158
159
|
"ecr:PutImage",
|
159
160
|
"ecr:GetAuthorizationToken",
|
160
161
|
],
|
162
|
+
"CloudBuild (Client)": [
|
163
|
+
"codebuild:CreateProject",
|
164
|
+
"codebuild:BatchGetBuilds",
|
165
|
+
],
|
166
|
+
"CloudBuild (Service)": [
|
167
|
+
"s3:GetObject",
|
168
|
+
"s3:GetObjectVersion",
|
169
|
+
"logs:CreateLogGroup",
|
170
|
+
"logs:CreateLogStream",
|
171
|
+
"logs:PutLogEvents",
|
172
|
+
"ecr:BatchGetImage",
|
173
|
+
"ecr:DescribeImages",
|
174
|
+
"ecr:BatchCheckLayerAvailability",
|
175
|
+
"ecr:GetDownloadUrlForLayer",
|
176
|
+
"ecr:InitiateLayerUpload",
|
177
|
+
"ecr:UploadLayerPart",
|
178
|
+
"ecr:CompleteLayerUpload",
|
179
|
+
"ecr:PutImage",
|
180
|
+
"ecr:GetAuthorizationToken",
|
181
|
+
],
|
161
182
|
"SageMaker (Client)": [
|
162
183
|
"sagemaker:CreatePipeline",
|
163
184
|
"sagemaker:StartPipelineExecution",
|
@@ -243,6 +264,7 @@ console.
|
|
243
264
|
param_ResourceName=f"zenml-{random_str(6).lower()}",
|
244
265
|
param_ZenMLServerURL=self.zenml_server_url,
|
245
266
|
param_ZenMLServerAPIToken=self.zenml_server_api_token,
|
267
|
+
param_CodeBuild="true",
|
246
268
|
)
|
247
269
|
# Encode the parameters as URL query parameters
|
248
270
|
query_params = "&".join([f"{k}={v}" for k, v in params.items()])
|
zenml/utils/archivable.py
CHANGED
@@ -15,11 +15,21 @@
|
|
15
15
|
|
16
16
|
import io
|
17
17
|
import tarfile
|
18
|
+
import zipfile
|
18
19
|
from abc import ABC, abstractmethod
|
19
20
|
from pathlib import Path
|
20
|
-
from typing import IO, Any, Dict
|
21
|
+
from typing import IO, Any, Dict, Optional
|
21
22
|
|
22
23
|
from zenml.io import fileio
|
24
|
+
from zenml.utils.enum_utils import StrEnum
|
25
|
+
|
26
|
+
|
27
|
+
class ArchiveType(StrEnum):
|
28
|
+
"""Archive types supported by the ZenML build context."""
|
29
|
+
|
30
|
+
TAR = "tar"
|
31
|
+
TAR_GZ = "tar.gz"
|
32
|
+
ZIP = "zip"
|
23
33
|
|
24
34
|
|
25
35
|
class Archivable(ABC):
|
@@ -81,52 +91,71 @@ class Archivable(ABC):
|
|
81
91
|
self._extra_files[file_destination.as_posix()] = f.read()
|
82
92
|
|
83
93
|
def write_archive(
|
84
|
-
self,
|
94
|
+
self,
|
95
|
+
output_file: IO[bytes],
|
96
|
+
archive_type: ArchiveType = ArchiveType.TAR_GZ,
|
85
97
|
) -> None:
|
86
98
|
"""Writes an archive of the build context to the given file.
|
87
99
|
|
88
100
|
Args:
|
89
101
|
output_file: The file to write the archive to.
|
90
|
-
|
102
|
+
archive_type: The type of archive to create.
|
91
103
|
"""
|
92
104
|
files = self.get_files()
|
93
105
|
extra_files = self.get_extra_files()
|
106
|
+
close_fileobj: Optional[Any] = None
|
107
|
+
fileobj: Any = output_file
|
94
108
|
|
95
|
-
if
|
96
|
-
|
97
|
-
|
98
|
-
# We don't use the builtin gzip functionality of the `tarfile`
|
99
|
-
# library as that one includes the tar filename and creation
|
100
|
-
# timestamp in the archive which causes the hash of the resulting
|
101
|
-
# file to be different each time. We use this hash to avoid
|
102
|
-
# duplicate uploads, which is why we pass empty values for filename
|
103
|
-
# and mtime here.
|
104
|
-
fileobj: Any = GzipFile(
|
105
|
-
filename="", mode="wb", fileobj=output_file, mtime=0.0
|
106
|
-
)
|
109
|
+
if archive_type == ArchiveType.ZIP:
|
110
|
+
fileobj = zipfile.ZipFile(output_file, "w", zipfile.ZIP_DEFLATED)
|
107
111
|
else:
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
112
|
+
if archive_type == ArchiveType.TAR_GZ:
|
113
|
+
from gzip import GzipFile
|
114
|
+
|
115
|
+
# We don't use the builtin gzip functionality of the `tarfile`
|
116
|
+
# library as that one includes the tar filename and creation
|
117
|
+
# timestamp in the archive which causes the hash of the resulting
|
118
|
+
# file to be different each time. We use this hash to avoid
|
119
|
+
# duplicate uploads, which is why we pass empty values for filename
|
120
|
+
# and mtime here.
|
121
|
+
close_fileobj = fileobj = GzipFile(
|
122
|
+
filename="", mode="wb", fileobj=output_file, mtime=0.0
|
123
|
+
)
|
124
|
+
fileobj = tarfile.open(mode="w", fileobj=fileobj)
|
125
|
+
|
126
|
+
try:
|
127
|
+
with fileobj as af:
|
128
|
+
for archive_path, file_path in files.items():
|
129
|
+
if archive_path in extra_files:
|
130
|
+
continue
|
131
|
+
if archive_type == ArchiveType.ZIP:
|
132
|
+
assert isinstance(af, zipfile.ZipFile)
|
133
|
+
af.write(file_path, arcname=archive_path)
|
119
134
|
else:
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
135
|
+
assert isinstance(af, tarfile.TarFile)
|
136
|
+
if info := af.gettarinfo(
|
137
|
+
file_path, arcname=archive_path
|
138
|
+
):
|
139
|
+
if info.isfile():
|
140
|
+
with open(file_path, "rb") as f:
|
141
|
+
af.addfile(info, f)
|
142
|
+
else:
|
143
|
+
af.addfile(info, None)
|
144
|
+
|
145
|
+
for archive_path, contents in extra_files.items():
|
146
|
+
contents_encoded = contents.encode("utf-8")
|
147
|
+
|
148
|
+
if archive_type == ArchiveType.ZIP:
|
149
|
+
assert isinstance(af, zipfile.ZipFile)
|
150
|
+
af.writestr(archive_path, contents_encoded)
|
151
|
+
else:
|
152
|
+
assert isinstance(af, tarfile.TarFile)
|
153
|
+
info = tarfile.TarInfo(archive_path)
|
154
|
+
info.size = len(contents_encoded)
|
155
|
+
af.addfile(info, io.BytesIO(contents_encoded))
|
156
|
+
finally:
|
157
|
+
if close_fileobj:
|
158
|
+
close_fileobj.close()
|
130
159
|
|
131
160
|
output_file.seek(0)
|
132
161
|
|
zenml/utils/code_utils.py
CHANGED
@@ -25,7 +25,7 @@ from zenml.client import Client
|
|
25
25
|
from zenml.io import fileio
|
26
26
|
from zenml.logger import get_logger
|
27
27
|
from zenml.utils import source_utils, string_utils
|
28
|
-
from zenml.utils.archivable import Archivable
|
28
|
+
from zenml.utils.archivable import Archivable, ArchiveType
|
29
29
|
|
30
30
|
if TYPE_CHECKING:
|
31
31
|
from git.repo.base import Repo
|
@@ -152,15 +152,19 @@ class CodeArchive(Archivable):
|
|
152
152
|
return all_files
|
153
153
|
|
154
154
|
def write_archive(
|
155
|
-
self,
|
155
|
+
self,
|
156
|
+
output_file: IO[bytes],
|
157
|
+
archive_type: ArchiveType = ArchiveType.TAR_GZ,
|
156
158
|
) -> None:
|
157
159
|
"""Writes an archive of the build context to the given file.
|
158
160
|
|
159
161
|
Args:
|
160
162
|
output_file: The file to write the archive to.
|
161
|
-
|
163
|
+
archive_type: The type of archive to create.
|
162
164
|
"""
|
163
|
-
super().write_archive(
|
165
|
+
super().write_archive(
|
166
|
+
output_file=output_file, archive_type=archive_type
|
167
|
+
)
|
164
168
|
archive_size = os.path.getsize(output_file.name)
|
165
169
|
if archive_size > 20 * 1024 * 1024:
|
166
170
|
logger.warning(
|
zenml/utils/docker_utils.py
CHANGED
@@ -266,6 +266,14 @@ def push_image(
|
|
266
266
|
logger.info("Finished pushing Docker image.")
|
267
267
|
|
268
268
|
image_name_without_tag, _ = image_name.rsplit(":", maxsplit=1)
|
269
|
+
|
270
|
+
image = docker_client.images.get(image_name)
|
271
|
+
repo_digests: List[str] = image.attrs["RepoDigests"]
|
272
|
+
|
273
|
+
for digest in repo_digests:
|
274
|
+
if digest.startswith(f"{image_name_without_tag}@"):
|
275
|
+
return digest
|
276
|
+
|
269
277
|
for info in reversed(aux_info):
|
270
278
|
try:
|
271
279
|
repo_digest = info["Digest"]
|
@@ -304,6 +312,7 @@ def get_image_digest(image_name: str) -> Optional[str]:
|
|
304
312
|
|
305
313
|
image = docker_client.images.get(image_name)
|
306
314
|
repo_digests = image.attrs["RepoDigests"]
|
315
|
+
|
307
316
|
if len(repo_digests) == 1:
|
308
317
|
return cast(str, repo_digests[0])
|
309
318
|
else:
|
{zenml_nightly-0.70.0.dev20241203.dist-info → zenml_nightly-0.70.0.dev20241204.dist-info}/RECORD
RENAMED
@@ -6,7 +6,7 @@ RELEASE_NOTES.md,sha256=DleauURHESDrTrcVzCVLqPiSM9NIAk5vldvEFMc7qlk,389375
|
|
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
|
9
|
+
zenml/VERSION,sha256=-A-FM4tTGBeZdWuioST8Yb1XGa9Iixr9mH9R98y-uNI,19
|
10
10
|
zenml/__init__.py,sha256=SkMObQA41ajqdZqGErN00S1Vf3KAxpLvbZ-OBy5uYoo,2130
|
11
11
|
zenml/actions/__init__.py,sha256=mrt6wPo73iKRxK754_NqsGyJ3buW7RnVeIGXr1xEw8Y,681
|
12
12
|
zenml/actions/base_action.py,sha256=UcaHev6BTuLDwuswnyaPjdA8AgUqB5xPZ-lRtuvf2FU,25553
|
@@ -126,8 +126,8 @@ zenml/hooks/__init__.py,sha256=lEifDzp1dkcatoBpCmmRNOEAh0vgrqtQQP_GH_4z1pk,1037
|
|
126
126
|
zenml/hooks/alerter_hooks.py,sha256=XJPhrnVimOayD2VjYBG_5D6R6sZ08rytwDHvvMD3lNI,3042
|
127
127
|
zenml/hooks/hook_validators.py,sha256=35VuolTruFoj6GUQf8n3PpQVMu54dp6apIGPui4FZu4,2516
|
128
128
|
zenml/image_builders/__init__.py,sha256=WVBxXTCiyhVhvGezovS5O-ypwC8V0YRihCOacd7i5iQ,1210
|
129
|
-
zenml/image_builders/base_image_builder.py,sha256
|
130
|
-
zenml/image_builders/build_context.py,sha256=
|
129
|
+
zenml/image_builders/base_image_builder.py,sha256=yFmtn8Y6PdNxie3F51tbpMf8zBhNRnNGr-ejTCEcq4Q,5491
|
130
|
+
zenml/image_builders/build_context.py,sha256=k38xERo4IXU9KKM-Zi5A2HzIp1pUZeWnhCPuRPSjkEQ,5864
|
131
131
|
zenml/image_builders/local_image_builder.py,sha256=R_zMpERtUCWLLDZg9kXuAQSWLtin1ve_rxpbUBiym7s,6448
|
132
132
|
zenml/integrations/README.md,sha256=hFIZwjsAItHjvDWVBqGSF-ZAeMsFR2GKX1Axl2g1Bz0,6190
|
133
133
|
zenml/integrations/__init__.py,sha256=GiLRzSCu1O9Jg5NSCRKVDWLIXtKuc90ozntqYjUHo08,4905
|
@@ -142,13 +142,16 @@ zenml/integrations/argilla/annotators/__init__.py,sha256=QjRMxIQ-skulcLN94GuHuuk
|
|
142
142
|
zenml/integrations/argilla/annotators/argilla_annotator.py,sha256=aIA5rcwfOYLnUVp2c_aaTAUnVW8GV9gP8myze_jY_qY,15586
|
143
143
|
zenml/integrations/argilla/flavors/__init__.py,sha256=MTogEeiZ1k7nLzGKok3azK_VhKUAJl0GL6OQvsvMlZo,917
|
144
144
|
zenml/integrations/argilla/flavors/argilla_annotator_flavor.py,sha256=NAy6QKLWYXHPTCoWc9RIovsngcRGMwseu3rdNjiCpo4,4473
|
145
|
-
zenml/integrations/aws/__init__.py,sha256=
|
145
|
+
zenml/integrations/aws/__init__.py,sha256=x-Ym8FlmeX7bAjL7zBxUp40U11IVZGyfcClRIeEydlI,2489
|
146
146
|
zenml/integrations/aws/container_registries/__init__.py,sha256=fOwo84MiaX_7XhNQEXeyVh8AyOlcIl6nSu_ig68GkSs,827
|
147
147
|
zenml/integrations/aws/container_registries/aws_container_registry.py,sha256=SCxKj_w79Ka0LdxYOdDmaXitketTQRDHrQ4XQ0_f4hs,6091
|
148
|
-
zenml/integrations/aws/flavors/__init__.py,sha256
|
148
|
+
zenml/integrations/aws/flavors/__init__.py,sha256=XYL9fpwKzeFfHCjakU0iJ3SyHVRJk63QT7luOy9Giek,1480
|
149
149
|
zenml/integrations/aws/flavors/aws_container_registry_flavor.py,sha256=GIDLOySz1zF08YSkmKIj89TxBqSLWueXLAHyxYwm-NI,4169
|
150
|
+
zenml/integrations/aws/flavors/aws_image_builder_flavor.py,sha256=XobJOw5ymbY22i7YHWGYOKDQoJQAqTeMIfvkADt-DDc,5343
|
150
151
|
zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py,sha256=UyHXFP9rn9DQ-Erd9Rtqun9GTcp3Rftbn2a9Xysh_TU,12826
|
151
152
|
zenml/integrations/aws/flavors/sagemaker_step_operator_flavor.py,sha256=OnNokixzGvOTBoZJQ5TDG3k4FFsP1pJmxbiij2VLW4s,5978
|
153
|
+
zenml/integrations/aws/image_builders/__init__.py,sha256=91hgH1OphG2i-vk-G8N4yKBFIzK89Wu7BK4-T5yOA7E,786
|
154
|
+
zenml/integrations/aws/image_builders/aws_image_builder.py,sha256=UcPYYYjJjfsicY3hV4OZeJt552AVmwPZPlv-AsG1g1I,11489
|
152
155
|
zenml/integrations/aws/orchestrators/__init__.py,sha256=Wh0Fhtt_uo6YrkvXY9kL0M478FL7XpapjoFreUZbgUg,794
|
153
156
|
zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py,sha256=OlnXr_KTWE8fOyO6bNmsCbRdRaCPqWGrUEX4gyVbD80,26801
|
154
157
|
zenml/integrations/aws/orchestrators/sagemaker_orchestrator_entrypoint_config.py,sha256=WXCWdVojIZxx5_3-g1T95S2vsJ-RLNGcp-V409wgme0,1555
|
@@ -325,7 +328,7 @@ zenml/integrations/kaniko/__init__.py,sha256=r40dq-xp9ji2xtfymwffryglCmsOZe2g1_9
|
|
325
328
|
zenml/integrations/kaniko/flavors/__init__.py,sha256=PpI7yUpjgLwwAi1ma5uTGihG4zUWxURiRTpHoHEXBIw,865
|
326
329
|
zenml/integrations/kaniko/flavors/kaniko_image_builder_flavor.py,sha256=iRICgO_f9RF1XOp7bO8qjmHm83v2NYqoJWorHZKhVzE,5080
|
327
330
|
zenml/integrations/kaniko/image_builders/__init__.py,sha256=X-ydYoG_6t4OWXDuCgfbugtVvPeOc97Kwf8RQ0KcPiU,787
|
328
|
-
zenml/integrations/kaniko/image_builders/kaniko_image_builder.py,sha256=
|
331
|
+
zenml/integrations/kaniko/image_builders/kaniko_image_builder.py,sha256=N4rLjIHYdw8v1CZvJP9G8RYpaMbERhzDyLP0UcEO3JA,13721
|
329
332
|
zenml/integrations/kubeflow/__init__.py,sha256=ab3v3sJBwo09vbyI2UQ5SnKfL0C9j8hrxR5ji-Xfswo,1791
|
330
333
|
zenml/integrations/kubeflow/flavors/__init__.py,sha256=l560A0oIpYeTpVVrdrVVYj-2-Y5CeyCSQMfwErZROxY,878
|
331
334
|
zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py,sha256=b7W4oASHLYN9o2n__-W3zajb_MXhPaY0UutecsW0Xw4,10381
|
@@ -334,7 +337,7 @@ zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py,sha256=H4rpm3
|
|
334
337
|
zenml/integrations/kubeflow/orchestrators/local_deployment_utils.py,sha256=qszoOdvBpgIp40XkncphXAr9dRKnyZzGiz2mJ56bYmw,15448
|
335
338
|
zenml/integrations/kubernetes/__init__.py,sha256=UzU5CaogX6ud5ChCK8JSZ06eoW18eIudbgntgPijYSc,1853
|
336
339
|
zenml/integrations/kubernetes/flavors/__init__.py,sha256=a5gU45qCj3FkLwl_uVjlIkL_2F5DHk-w1gdcZrvVjBI,1266
|
337
|
-
zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py,sha256=
|
340
|
+
zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py,sha256=al3EwEhwbG2uCHpkfC_4J-nOPCNW-LdJ568X0hPAvxE,8312
|
338
341
|
zenml/integrations/kubernetes/flavors/kubernetes_step_operator_flavor.py,sha256=ILN-H4cl7z3i4ltb4UBs55wbtIo871b4ib28pYkQoyQ,5605
|
339
342
|
zenml/integrations/kubernetes/orchestrators/__init__.py,sha256=TJID3OTieZBox36WpQpzD0jdVRA_aZVcs_bNtfXS8ik,811
|
340
343
|
zenml/integrations/kubernetes/orchestrators/kube_utils.py,sha256=0Cj1RoiuXL4oACnfyzEpOiCTnHt_YoF5ml3bhobyOEg,12195
|
@@ -369,7 +372,7 @@ zenml/integrations/lightgbm/materializers/lightgbm_booster_materializer.py,sha25
|
|
369
372
|
zenml/integrations/lightgbm/materializers/lightgbm_dataset_materializer.py,sha256=q1L1cke0j9hYNbruPxaWDDgp0thNPNHZA0gH4gyfugI,2856
|
370
373
|
zenml/integrations/lightning/__init__.py,sha256=Wyj8P7ihX8DpOO4bmggM_Pq3HDwU02fjdB51s5sHJSA,1521
|
371
374
|
zenml/integrations/lightning/flavors/__init__.py,sha256=Ma949QQTTYw1Zw1fo6zSUXomXfXQRTPHY9N2wZGweMA,883
|
372
|
-
zenml/integrations/lightning/flavors/lightning_orchestrator_flavor.py,sha256=
|
375
|
+
zenml/integrations/lightning/flavors/lightning_orchestrator_flavor.py,sha256=U6ewra4C8cSrnRQTlEJrY2ouR4XJ3ShnAg1fDoC9fFQ,5259
|
373
376
|
zenml/integrations/lightning/orchestrators/__init__.py,sha256=rUaCQPcbpAPy57jx8ZqEOjTJv8zigT_nCPrMdfQJ8OU,1030
|
374
377
|
zenml/integrations/lightning/orchestrators/lightning_orchestrator.py,sha256=6XGg-cKKRNCot6DI9ub4oZWF4_K41OHs1lT90FL8VsM,24712
|
375
378
|
zenml/integrations/lightning/orchestrators/lightning_orchestrator_entrypoint.py,sha256=VHVXZ6jZ0URLhwaIPMyDmrnrBpYvzDnqQdIoSVM9m6E,11506
|
@@ -478,7 +481,7 @@ zenml/integrations/sklearn/materializers/__init__.py,sha256=vHIx7njuVcP_kGbyECgJ
|
|
478
481
|
zenml/integrations/sklearn/materializers/sklearn_materializer.py,sha256=IaE8DS9L2gjfRVv8RT8p7ls7cJJ5qzt6hRgdpL6pp20,1562
|
479
482
|
zenml/integrations/skypilot/__init__.py,sha256=PzNuJJykzfu34pTC4kSD18ARyGysuhzEW8oLTm4oHuo,612
|
480
483
|
zenml/integrations/skypilot/flavors/__init__.py,sha256=PzNuJJykzfu34pTC4kSD18ARyGysuhzEW8oLTm4oHuo,612
|
481
|
-
zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py,sha256=
|
484
|
+
zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py,sha256=UPHfsB75CDZ8ecxxlL8aTo3IGIVuCAU_USBHzhULMuc,6675
|
482
485
|
zenml/integrations/skypilot/orchestrators/__init__.py,sha256=elo6QiImzys1m_bgu96U1HCVRepHQI1m7Jgqn6aEJ4Q,844
|
483
486
|
zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py,sha256=Oxd_8MEDd5JFovPgHE5xWreLTBQhTJZPA1nLYpvgIa0,14290
|
484
487
|
zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py,sha256=5sq04vu2ArsyW56wvH8CRLG8kmeaSkPYPzirGGe7mds,9737
|
@@ -595,7 +598,7 @@ zenml/login/pro/utils.py,sha256=PnQ90eiqijY-VKqd974HzCtAosrHhzOxL1NpqZbpE5M,5355
|
|
595
598
|
zenml/login/web_login.py,sha256=NkFKnPj8qDZAb2FfDW8ZvkWrGiurf7YiYEEs5m844aM,9037
|
596
599
|
zenml/materializers/__init__.py,sha256=maME5CxKcgOkIFwG_iARt1-tuW8u8ZhTzfw50uyv_BA,1667
|
597
600
|
zenml/materializers/base_materializer.py,sha256=M4hwkw7PB0LskCE92r-S35011l7DlFemit-EuUCW3Nc,14002
|
598
|
-
zenml/materializers/built_in_materializer.py,sha256=
|
601
|
+
zenml/materializers/built_in_materializer.py,sha256=AFrCW_LErey2ws6vfLTbBP5gx3IFi05YPEmT4BA-CzY,15668
|
599
602
|
zenml/materializers/cloudpickle_materializer.py,sha256=x8a6jEMTky6N2YVHiwrnGWSfVJUpiy-4kQsD2Aqj_E0,4837
|
600
603
|
zenml/materializers/materializer_registry.py,sha256=ic-aWhJ2Ex9F_rml2dDVAxhRfW3nd71QMxzfTPP6BIM,4002
|
601
604
|
zenml/materializers/numpy_materializer.py,sha256=OLcHF9Z0tAqQ_U8TraA0vGmZjHoT7eT_XevncIutt0M,1715
|
@@ -674,7 +677,7 @@ zenml/models/v2/misc/service_connector_type.py,sha256=jGJLvIsBB87ZIEeZCLLueUf28H
|
|
674
677
|
zenml/models/v2/misc/stack_deployment.py,sha256=PgQevLjvHTpsecY_rzrXesr7jiGms7rH_QbFtI2ZIaA,3768
|
675
678
|
zenml/models/v2/misc/user_auth.py,sha256=1-yafNA9qK4wL8ToROjaklTVI7Mj9va0t80_4wm7w3U,6988
|
676
679
|
zenml/orchestrators/__init__.py,sha256=p4Y9Ni7Lp33fZ6UrjgI7qu-rrg8LrlyafCM-K1WC81w,1961
|
677
|
-
zenml/orchestrators/base_orchestrator.py,sha256=
|
680
|
+
zenml/orchestrators/base_orchestrator.py,sha256=vQsMUhhZUX34EyJbYpXB4F0iPmrOHaVLtsKM0vuN1yE,12646
|
678
681
|
zenml/orchestrators/cache_utils.py,sha256=J5sMmgy-qRJVtTWt5hDjSAR6vPPulOhMJu0m-Y1onO8,4327
|
679
682
|
zenml/orchestrators/containerized_orchestrator.py,sha256=rdebgBW0Bk--JcHcT0NpLkAbyhY0VS5xO1uwWEgkLpA,3230
|
680
683
|
zenml/orchestrators/dag_runner.py,sha256=0F0zOy90ZHad_YUiwG_47JiH7KEVFQ5tLen0kGPvppk,6940
|
@@ -683,7 +686,7 @@ zenml/orchestrators/local/__init__.py,sha256=qlU91hgqGKeycw-Qntrn-iMuoMTaNrq-Rgf
|
|
683
686
|
zenml/orchestrators/local/local_orchestrator.py,sha256=VCVemtPtW1bXvEM80wgaqdmoXiPrVOTNITXJ2MauTaw,5505
|
684
687
|
zenml/orchestrators/local_docker/__init__.py,sha256=k8J68ydy6HmmvE9tWo32g761H8P_Dw4AxWNf4UMpsbs,669
|
685
688
|
zenml/orchestrators/local_docker/local_docker_orchestrator.py,sha256=kzxvmKwEi7ihXfeoopIUwipSorvpB4Lw2pdCAOcZaZ0,9190
|
686
|
-
zenml/orchestrators/output_utils.py,sha256=
|
689
|
+
zenml/orchestrators/output_utils.py,sha256=01vqke1ZfmfuLpgxNerF-QL2wA0VPv1zUdvlMw0OwUY,3508
|
687
690
|
zenml/orchestrators/publish_utils.py,sha256=oLvcjCx_WT3_RITB86WNEaUe_qMsPMTD_warAvjS2dA,4752
|
688
691
|
zenml/orchestrators/step_launcher.py,sha256=iSrp6X-fIfuqCBS4zCgHLKlV2P08lFPf7wwBjT69LRA,17922
|
689
692
|
zenml/orchestrators/step_run_utils.py,sha256=N1_Sd8q9i5u-uWqhTH-gssxf-XkF3vbSDMwu1byyCSk,20424
|
@@ -712,7 +715,7 @@ zenml/service_connectors/__init__.py,sha256=gIBAVUPBZtdO6JtEBCixy9YG4wZRA1mnaxaG
|
|
712
715
|
zenml/service_connectors/docker_service_connector.py,sha256=_6WPqYCcSUf8JPakipbkJRvaN2ghhY7zCr38WCHG0SI,13218
|
713
716
|
zenml/service_connectors/service_connector.py,sha256=HW8dTE826ZSD1vWQlqQRm8XYq08v7tDZQ8ORnJ5rTcE,55351
|
714
717
|
zenml/service_connectors/service_connector_registry.py,sha256=mCabyKAr7Y6bcAbIFXbir9YrHczDe1ZJ8Bks5bOQouk,9658
|
715
|
-
zenml/service_connectors/service_connector_utils.py,sha256=
|
718
|
+
zenml/service_connectors/service_connector_utils.py,sha256=x_8rxl2yQc8VvvaWYXyxUxVijo7CCdlnod0z-jd-vUk,18056
|
716
719
|
zenml/services/__init__.py,sha256=8aSLtYlX9EVLB1Se1I4dbhZdTqrjNrAfsn1d_RCc_nk,2800
|
717
720
|
zenml/services/container/__init__.py,sha256=dFHcmlXgNXjUaCR18oGQJ19-I_6f3UeAUURHjqldjTs,668
|
718
721
|
zenml/services/container/container_service.py,sha256=DJIK7DD53Q_mgZByM0oeIyAgkrwN12T5E3QCWjubkLs,18383
|
@@ -736,7 +739,7 @@ zenml/stack/stack_component.py,sha256=4V111uBLpmsPaNffaQS-fLuz163WFEjsmIFzb_lq7i
|
|
736
739
|
zenml/stack/stack_validator.py,sha256=hWbvvGIeWLj6NwSsF4GCc6RAxAWvxHXTcBZL9nJvcak,3111
|
737
740
|
zenml/stack/utils.py,sha256=qHMFi8SVMSDFeZTFO4KkvaLUbF-l3B0_JZ5SSMxYrwI,6406
|
738
741
|
zenml/stack_deployments/__init__.py,sha256=-7593cQ_ZgRn774Ol-8AKXXQquIU4DSiaThVEr6TfWM,644
|
739
|
-
zenml/stack_deployments/aws_stack_deployment.py,sha256=
|
742
|
+
zenml/stack_deployments/aws_stack_deployment.py,sha256=FnkiSwSMiM9O8KVTQmGfIKjsp5RkOiO-AbOsr7cd3zE,12358
|
740
743
|
zenml/stack_deployments/azure_stack_deployment.py,sha256=E0PhlmC_2Urf_7k1U7EoOHU21CbhY_3jZG0wXO1NcWI,13032
|
741
744
|
zenml/stack_deployments/gcp_stack_deployment.py,sha256=RD9Z0cZicZexUyK2YE0855LHu_VGOrLUnzy-QnrBRnA,12596
|
742
745
|
zenml/stack_deployments/stack_deployment.py,sha256=hrupbDuIfI6YhzHcmxNLsfnS7Qu_Pgv_5didiyv0msk,7572
|
@@ -754,16 +757,16 @@ zenml/steps/step_invocation.py,sha256=ETfOaV-P4_iXGk9y1-xK54Kfg2QRYaGoj_jTyEYZfb
|
|
754
757
|
zenml/steps/utils.py,sha256=hEIOhxHp69WO-9YX6sBpZrVLK6fytqvdzhW5p1aB09M,18580
|
755
758
|
zenml/types.py,sha256=LhGWJ4t3nybBk1l9Ox3tqqHbTYSuCqhkRsL5FqO6yf4,1206
|
756
759
|
zenml/utils/__init__.py,sha256=jaMTbjm8tLYkaRoxlZ0Em4ye_ZHOHKgP2goPTTiYGUQ,797
|
757
|
-
zenml/utils/archivable.py,sha256=
|
760
|
+
zenml/utils/archivable.py,sha256=QuLe1IhyABTrE6Y0hAT3tKjaUCpcze5ffZ_RKoKtJwY,6549
|
758
761
|
zenml/utils/callback_registry.py,sha256=QBWdaraLAxBxi8DKbv9X1SUpTKDhhj-XE0JomB2Ax2Y,2411
|
759
762
|
zenml/utils/code_repository_utils.py,sha256=CobRYMYfP2yNoA0hcu_WRz5oAff_jY95oyLCHz4fDOo,4734
|
760
|
-
zenml/utils/code_utils.py,sha256=
|
763
|
+
zenml/utils/code_utils.py,sha256=y7_vmqYv_e11xekFjK7Dm4LkFu6SGl73tr2fVxBAK3s,11336
|
761
764
|
zenml/utils/cuda_utils.py,sha256=RR21m__Zs-OnI5n-veFUzWniZjwLSbalHE5QV3jK1Hw,1624
|
762
765
|
zenml/utils/daemon.py,sha256=GZ7Dx6GLHK04SR50wBxpKYmFhxPBfdLWxJiAWzJC6cM,11863
|
763
766
|
zenml/utils/dashboard_utils.py,sha256=JyT-rOsqipazmImXBB-UzCg0GJ3UNzVCFdMcQisInfQ,5379
|
764
767
|
zenml/utils/deprecation_utils.py,sha256=2cyeUeYas2OCcOcUJul2EGKd5zR_0KOjm6fKCshtFm0,6253
|
765
768
|
zenml/utils/dict_utils.py,sha256=i7KAaKrkaWA_cG5IvVfMnr0CwWlBJ7KAsGvP2wxjZI8,2667
|
766
|
-
zenml/utils/docker_utils.py,sha256=
|
769
|
+
zenml/utils/docker_utils.py,sha256=QvkKnvIYSKAhW7mErXwSaQ432-q1LAsLjo2YWSXD8Bk,13889
|
767
770
|
zenml/utils/downloaded_repository_context.py,sha256=S660PSSQ3dsNBA0qAj8ap_Thyw1n6x4VDcRWbCMDP2M,1502
|
768
771
|
zenml/utils/enum_utils.py,sha256=0fA0B9v9Wjutuqlu_owUoOit1utIw2UH5J6YHXSqhLU,1368
|
769
772
|
zenml/utils/env_utils.py,sha256=2--2DDUt3gPOvCNVyobBtAciikQ0OEXs5WWp7NvYuKo,5276
|
@@ -1276,8 +1279,8 @@ zenml/zen_stores/secrets_stores/sql_secrets_store.py,sha256=Bq1djrUP9saoD7vECjS7
|
|
1276
1279
|
zenml/zen_stores/sql_zen_store.py,sha256=gq7hwCqXuvABUGHoo6J_fOdf4PGuN88BFWE84KK_-UM,408283
|
1277
1280
|
zenml/zen_stores/template_utils.py,sha256=EKYBgmDLTS_PSMWaIO5yvHPLiQvMqHcsAe6NUCrv-i4,9068
|
1278
1281
|
zenml/zen_stores/zen_store_interface.py,sha256=vf2gKBWfUUPtcGZC35oQB6pPNVzWVyQC8nWxVLjfrxM,92692
|
1279
|
-
zenml_nightly-0.70.0.
|
1280
|
-
zenml_nightly-0.70.0.
|
1281
|
-
zenml_nightly-0.70.0.
|
1282
|
-
zenml_nightly-0.70.0.
|
1283
|
-
zenml_nightly-0.70.0.
|
1282
|
+
zenml_nightly-0.70.0.dev20241204.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
|
1283
|
+
zenml_nightly-0.70.0.dev20241204.dist-info/METADATA,sha256=SsbWnr1H59o25vg7YOc1twHRrEODkGD23akgH9vanYU,21208
|
1284
|
+
zenml_nightly-0.70.0.dev20241204.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
1285
|
+
zenml_nightly-0.70.0.dev20241204.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
|
1286
|
+
zenml_nightly-0.70.0.dev20241204.dist-info/RECORD,,
|
{zenml_nightly-0.70.0.dev20241203.dist-info → zenml_nightly-0.70.0.dev20241204.dist-info}/LICENSE
RENAMED
File without changes
|
{zenml_nightly-0.70.0.dev20241203.dist-info → zenml_nightly-0.70.0.dev20241204.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|