Skip to content

Commit 5a77dbe

Browse files
committed
AWS Image Builder implementation
1 parent 0b3294e commit 5a77dbe

File tree

11 files changed

+570
-216
lines changed

11 files changed

+570
-216
lines changed

src/zenml/image_builders/base_image_builder.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from zenml.logger import get_logger
2626
from zenml.stack import Flavor, StackComponent
2727
from zenml.stack.stack_component import StackComponentConfig
28+
from zenml.utils.archivable import ArchiveType
2829

2930
if TYPE_CHECKING:
3031
from zenml.container_registries import BaseContainerRegistry
@@ -100,6 +101,7 @@ def build(
100101
def _upload_build_context(
101102
build_context: "BuildContext",
102103
parent_path_directory_name: str,
104+
archive_type: ArchiveType = ArchiveType.TAR_GZ,
103105
) -> str:
104106
"""Uploads a Docker image build context to a remote location.
105107
@@ -109,6 +111,7 @@ def _upload_build_context(
109111
the build context to. It will be appended to the artifact
110112
store path to create the parent path where the build context
111113
will be uploaded to.
114+
archive_type: The type of archive to create.
112115
113116
Returns:
114117
The path to the uploaded build context.
@@ -119,15 +122,15 @@ def _upload_build_context(
119122

120123
hash_ = hashlib.sha1() # nosec
121124
with tempfile.NamedTemporaryFile(mode="w+b", delete=False) as f:
122-
build_context.write_archive(f, use_gzip=True)
125+
build_context.write_archive(f, archive_type)
123126

124127
while True:
125128
data = f.read(64 * 1024)
126129
if not data:
127130
break
128131
hash_.update(data)
129132

130-
filename = f"{hash_.hexdigest()}.tar.gz"
133+
filename = f"{hash_.hexdigest()}.{archive_type.value}"
131134
filepath = f"{parent_path}/{filename}"
132135
if not fileio.exists(filepath):
133136
logger.info("Uploading build context to `%s`.", filepath)

src/zenml/image_builders/build_context.py

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from zenml.io import fileio
2121
from zenml.logger import get_logger
2222
from zenml.utils import io_utils, string_utils
23-
from zenml.utils.archivable import Archivable
23+
from zenml.utils.archivable import Archivable, ArchiveType
2424

2525
logger = get_logger(__name__)
2626

@@ -69,28 +69,19 @@ def dockerignore_file(self) -> Optional[str]:
6969
return None
7070

7171
def write_archive(
72-
self, output_file: IO[bytes], use_gzip: bool = True
72+
self,
73+
output_file: IO[bytes],
74+
archive_type: ArchiveType = ArchiveType.TAR_GZ,
7375
) -> None:
7476
"""Writes an archive of the build context to the given file.
7577
7678
Args:
7779
output_file: The file to write the archive to.
78-
use_gzip: Whether to use `gzip` to compress the file.
80+
archive_type: The type of archive to create.
7981
"""
80-
from docker.utils import build as docker_build_utils
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)
9283

93-
build_context_size = os.path.getsize(context_archive.name)
84+
build_context_size = os.path.getsize(output_file.name)
9485
if (
9586
self._root
9687
and build_context_size > 50 * 1024 * 1024

src/zenml/integrations/aws/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
AWS_CONNECTOR_TYPE = "aws"
3434
AWS_RESOURCE_TYPE = "aws-generic"
3535
S3_RESOURCE_TYPE = "s3-bucket"
36+
AWS_IMAGE_BUILDER_FLAVOR = "aws"
3637

3738
class AWSIntegration(Integration):
3839
"""Definition of AWS integration for ZenML."""
@@ -59,12 +60,14 @@ def flavors(cls) -> List[Type[Flavor]]:
5960
"""
6061
from zenml.integrations.aws.flavors import (
6162
AWSContainerRegistryFlavor,
63+
AWSImageBuilderFlavor,
6264
SagemakerOrchestratorFlavor,
6365
SagemakerStepOperatorFlavor,
6466
)
6567

6668
return [
6769
AWSContainerRegistryFlavor,
70+
AWSImageBuilderFlavor,
6871
SagemakerStepOperatorFlavor,
6972
SagemakerOrchestratorFlavor,
7073
]

src/zenml/integrations/aws/flavors/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
AWSContainerRegistryConfig,
1818
AWSContainerRegistryFlavor,
1919
)
20+
from zenml.integrations.aws.flavors.aws_image_builder_flavor import (
21+
AWSImageBuilderConfig,
22+
AWSImageBuilderFlavor,
23+
)
2024
from zenml.integrations.aws.flavors.sagemaker_orchestrator_flavor import (
2125
SagemakerOrchestratorConfig,
2226
SagemakerOrchestratorFlavor,
@@ -29,6 +33,8 @@
2933
__all__ = [
3034
"AWSContainerRegistryFlavor",
3135
"AWSContainerRegistryConfig",
36+
"AWSImageBuilderConfig",
37+
"AWSImageBuilderFlavor",
3238
"SagemakerStepOperatorFlavor",
3339
"SagemakerStepOperatorConfig",
3440
"SagemakerOrchestratorFlavor",
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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, 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+
from zenml.utils.secret_utils import SecretField
26+
27+
if TYPE_CHECKING:
28+
from zenml.integrations.aws.image_builders import AWSImageBuilder
29+
30+
31+
class AWSImageBuilderConfig(BaseImageBuilderConfig):
32+
"""AWS Code Build image builder configuration.
33+
34+
Attributes:
35+
code_build_project: The name of the AWS CodeBuild project to use to
36+
build the image.
37+
aws_access_key_id: The AWS access key ID to use to authenticate to AWS.
38+
If not provided, the value from the default AWS config will be used.
39+
aws_secret_access_key: The AWS secret access key to use to authenticate
40+
to AWS. If not provided, the value from the default AWS config will
41+
be used.
42+
aws_auth_role_arn: The ARN of an intermediate IAM role to assume when
43+
authenticating to AWS.
44+
region: The AWS region where the processing job will be run. If not
45+
provided, the value from the default AWS config will be used.
46+
implicit_auth: Whether to use implicit authentication to authenticate
47+
the AWS Code Build build to the container registry. If set to False,
48+
the container registry credentials must be explicitly configured for
49+
the container registry stack component or the container registry
50+
stack component must be linked to a service connector.
51+
NOTE: When implicit_auth is set to False, the container registry
52+
credentials will be passed to the AWS Code Build build as
53+
environment variables. This is not recommended for production use
54+
unless your service connector is configured to generate short-lived
55+
credentials.
56+
"""
57+
58+
code_build_project: str
59+
aws_access_key_id: Optional[str] = SecretField(default=None)
60+
aws_secret_access_key: Optional[str] = SecretField(default=None)
61+
aws_auth_role_arn: Optional[str] = None
62+
region: Optional[str] = None
63+
implicit_auth: bool = True
64+
65+
66+
class AWSImageBuilderFlavor(BaseImageBuilderFlavor):
67+
"""AWS Code Build image builder flavor."""
68+
69+
@property
70+
def name(self) -> str:
71+
"""The flavor name.
72+
73+
Returns:
74+
The name of the flavor.
75+
"""
76+
return AWS_IMAGE_BUILDER_FLAVOR
77+
78+
@property
79+
def service_connector_requirements(
80+
self,
81+
) -> Optional[ServiceConnectorRequirements]:
82+
"""Service connector resource requirements for service connectors.
83+
84+
Specifies resource requirements that are used to filter the available
85+
service connector types that are compatible with this flavor.
86+
87+
Returns:
88+
Requirements for compatible service connectors, if a service
89+
connector is required for this flavor.
90+
"""
91+
return ServiceConnectorRequirements(
92+
connector_type=AWS_CONNECTOR_TYPE,
93+
resource_type=AWS_RESOURCE_TYPE,
94+
)
95+
96+
@property
97+
def docs_url(self) -> Optional[str]:
98+
"""A url to point at docs explaining this flavor.
99+
100+
Returns:
101+
A flavor docs url.
102+
"""
103+
return self.generate_default_docs_url()
104+
105+
@property
106+
def sdk_docs_url(self) -> Optional[str]:
107+
"""A url to point at SDK docs explaining this flavor.
108+
109+
Returns:
110+
A flavor SDK docs url.
111+
"""
112+
return self.generate_default_sdk_docs_url()
113+
114+
@property
115+
def logo_url(self) -> str:
116+
"""A url to represent the flavor in the dashboard.
117+
118+
Returns:
119+
The flavor logo.
120+
"""
121+
return "https://public-flavor-logos.s3.eu-central-1.amazonaws.com/image_builder/aws.png"
122+
123+
@property
124+
def config_class(self) -> Type[BaseImageBuilderConfig]:
125+
"""The config class.
126+
127+
Returns:
128+
The config class.
129+
"""
130+
return AWSImageBuilderConfig
131+
132+
@property
133+
def implementation_class(self) -> Type["AWSImageBuilder"]:
134+
"""Implementation class.
135+
136+
Returns:
137+
The implementation class.
138+
"""
139+
from zenml.integrations.aws.image_builders import AWSImageBuilder
140+
141+
return AWSImageBuilder
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 commit comments

Comments
 (0)