zenml-nightly 0.70.0.dev20241201__py3-none-any.whl → 0.71.0.dev20241220__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. README.md +4 -4
  2. RELEASE_NOTES.md +112 -0
  3. zenml/VERSION +1 -1
  4. zenml/artifacts/artifact_config.py +8 -5
  5. zenml/artifacts/utils.py +3 -1
  6. zenml/cli/__init__.py +4 -4
  7. zenml/cli/base.py +1 -1
  8. zenml/cli/pipeline.py +48 -79
  9. zenml/cli/server.py +19 -19
  10. zenml/client.py +54 -2
  11. zenml/config/secret_reference_mixin.py +1 -1
  12. zenml/config/server_config.py +4 -0
  13. zenml/constants.py +10 -0
  14. zenml/image_builders/base_image_builder.py +5 -2
  15. zenml/image_builders/build_context.py +7 -16
  16. zenml/integrations/aws/__init__.py +3 -0
  17. zenml/integrations/aws/flavors/__init__.py +6 -0
  18. zenml/integrations/aws/flavors/aws_image_builder_flavor.py +146 -0
  19. zenml/integrations/aws/image_builders/__init__.py +20 -0
  20. zenml/integrations/aws/image_builders/aws_image_builder.py +307 -0
  21. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +1 -1
  22. zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +2 -1
  23. zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +11 -0
  24. zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +0 -1
  25. zenml/integrations/lightning/flavors/lightning_orchestrator_flavor.py +11 -0
  26. zenml/integrations/neptune/experiment_trackers/neptune_experiment_tracker.py +7 -5
  27. zenml/integrations/neptune/experiment_trackers/run_state.py +69 -53
  28. zenml/integrations/registry.py +2 -2
  29. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +12 -0
  30. zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +13 -5
  31. zenml/materializers/built_in_materializer.py +1 -1
  32. zenml/model/model.py +12 -16
  33. zenml/model/utils.py +3 -1
  34. zenml/models/v2/base/filter.py +26 -30
  35. zenml/models/v2/base/scoped.py +258 -5
  36. zenml/models/v2/core/artifact_version.py +15 -26
  37. zenml/models/v2/core/code_repository.py +1 -12
  38. zenml/models/v2/core/component.py +5 -46
  39. zenml/models/v2/core/flavor.py +1 -11
  40. zenml/models/v2/core/model.py +1 -57
  41. zenml/models/v2/core/model_version.py +5 -33
  42. zenml/models/v2/core/model_version_artifact.py +11 -3
  43. zenml/models/v2/core/model_version_pipeline_run.py +14 -3
  44. zenml/models/v2/core/pipeline.py +47 -55
  45. zenml/models/v2/core/pipeline_build.py +67 -12
  46. zenml/models/v2/core/pipeline_deployment.py +0 -10
  47. zenml/models/v2/core/pipeline_run.py +91 -29
  48. zenml/models/v2/core/run_template.py +21 -29
  49. zenml/models/v2/core/schedule.py +0 -10
  50. zenml/models/v2/core/secret.py +0 -14
  51. zenml/models/v2/core/service.py +9 -16
  52. zenml/models/v2/core/service_connector.py +0 -11
  53. zenml/models/v2/core/stack.py +21 -30
  54. zenml/models/v2/core/step_run.py +18 -14
  55. zenml/models/v2/core/trigger.py +19 -3
  56. zenml/orchestrators/base_orchestrator.py +13 -1
  57. zenml/orchestrators/output_utils.py +5 -1
  58. zenml/orchestrators/step_launcher.py +9 -13
  59. zenml/orchestrators/step_run_utils.py +8 -204
  60. zenml/orchestrators/utils.py +55 -27
  61. zenml/pipelines/build_utils.py +12 -0
  62. zenml/service_connectors/service_connector_utils.py +3 -9
  63. zenml/stack/stack_component.py +1 -1
  64. zenml/stack_deployments/aws_stack_deployment.py +22 -0
  65. zenml/utils/archivable.py +65 -36
  66. zenml/utils/code_utils.py +8 -4
  67. zenml/utils/docker_utils.py +9 -0
  68. zenml/zen_server/auth.py +9 -10
  69. zenml/zen_server/dashboard/assets/{404-NVXKFp-x.js → 404-Cqu3EDCm.js} +1 -1
  70. zenml/zen_server/dashboard/assets/{@reactflow-CK0KJUen.js → @reactflow-D2Y7BWwz.js} +1 -1
  71. zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-DezXKmDf.js → AlertDialogDropdownItem-BHd71pVS.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{CodeSnippet-JzR8CEtw.js → CodeSnippet-DIonwetW.js} +1 -1
  73. zenml/zen_server/dashboard/assets/{CollapsibleCard-DQW_ktMO.js → CollapsibleCard-CDnC97pB.js} +1 -1
  74. zenml/zen_server/dashboard/assets/{Commands-DL2kwkRd.js → Commands-BVEXKAOj.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{ComponentBadge-D_g62Wv8.js → ComponentBadge-CrRvovox.js} +1 -1
  76. zenml/zen_server/dashboard/assets/{CopyButton-LNcWaa14.js → CopyButton-B6wGAhQv.js} +1 -1
  77. zenml/zen_server/dashboard/assets/{CsvVizualization-DknpE5ej.js → CsvVizualization-CjcT7LMm.js} +5 -5
  78. zenml/zen_server/dashboard/assets/DeleteAlertDialog-D2ELtM2W.js +1 -0
  79. zenml/zen_server/dashboard/assets/{DialogItem-Bxf8FuAT.js → DialogItem-DXIMhBgU.js} +1 -1
  80. zenml/zen_server/dashboard/assets/{Error-DYflYyps.js → Error-B8uUfTpL.js} +1 -1
  81. zenml/zen_server/dashboard/assets/{ExecutionStatus-C7zyIQKZ.js → ExecutionStatus-ibAdY-dG.js} +1 -1
  82. zenml/zen_server/dashboard/assets/{Helpbox-oYSGpLqd.js → Helpbox-BfAfhKHw.js} +1 -1
  83. zenml/zen_server/dashboard/assets/{Infobox-Cx4xGoXR.js → Infobox-M_SMOu96.js} +1 -1
  84. zenml/zen_server/dashboard/assets/{InlineAvatar-DiGOWNKF.js → InlineAvatar-DBA0a0-a.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{NestedCollapsible-DYbgyKxK.js → NestedCollapsible-DpgmEFKw.js} +1 -1
  86. zenml/zen_server/dashboard/assets/{Partials-03iZf8-N.js → Partials-D_ldD9if.js} +1 -1
  87. zenml/zen_server/dashboard/assets/{ProBadge-D_EB8HNo.js → ProBadge-DQbfFotM.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{ProCta-DqNS4v3x.js → ProCta-Bcpb4rcY.js} +1 -1
  89. zenml/zen_server/dashboard/assets/{ProviderIcon-Bki2aw8w.js → ProviderIcon-BZpgPigN.js} +1 -1
  90. zenml/zen_server/dashboard/assets/{ProviderRadio-8f43sPD4.js → ProviderRadio-DWPnMuQ1.js} +1 -1
  91. zenml/zen_server/dashboard/assets/RunSelector-DgRGaAc6.js +1 -0
  92. zenml/zen_server/dashboard/assets/{RunsBody-07YEO7qI.js → RunsBody-KecfSkjY.js} +1 -1
  93. zenml/zen_server/dashboard/assets/{SearchField-lp1KgU4e.js → SearchField-n-ILHnaP.js} +1 -1
  94. zenml/zen_server/dashboard/assets/{SecretTooltip-CgnbyeOx.js → SecretTooltip-B8MrX5yu.js} +1 -1
  95. zenml/zen_server/dashboard/assets/{SetPassword-CpP418A2.js → SetPassword-B_IVq_wg.js} +1 -1
  96. zenml/zen_server/dashboard/assets/StackList-TWPBYnkF.js +1 -0
  97. zenml/zen_server/dashboard/assets/{Tabs-BktHkCJJ.js → Tabs-Rg857zmd.js} +1 -1
  98. zenml/zen_server/dashboard/assets/{Tick-BlMoIlJT.js → Tick-COg4A-xo.js} +1 -1
  99. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-Sc0A0pP-.js → UpdatePasswordSchemas-C6Aj3hm6.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{UsageReason-YYduL4fj.js → UsageReason-BTLbx7w4.js} +1 -1
  101. zenml/zen_server/dashboard/assets/{WizardFooter-dgmizSJC.js → WizardFooter-BCAj69Vj.js} +1 -1
  102. zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-D-c2G6lV.js → all-pipeline-runs-query-DMXkDrV2.js} +1 -1
  103. zenml/zen_server/dashboard/assets/code-snippets-CqONne41.js +13 -0
  104. zenml/zen_server/dashboard/assets/{create-stack-DM_JPgef.js → create-stack-HfdbhLs4.js} +1 -1
  105. zenml/zen_server/dashboard/assets/dates-3pMLCNrD.js +1 -0
  106. zenml/zen_server/dashboard/assets/delete-run-DZ4hIXff.js +1 -0
  107. zenml/zen_server/dashboard/assets/{form-schemas-K6FYKjwa.js → form-schemas-B0AVEd9b.js} +1 -1
  108. zenml/zen_server/dashboard/assets/{index-BAkC7FXi.js → index-DPqSWjug.js} +1 -1
  109. zenml/zen_server/dashboard/assets/{index-CEV4Cvaf.js → index-DScjfBRb.js} +1 -1
  110. zenml/zen_server/dashboard/assets/index-DXvT1_Um.css +1 -0
  111. zenml/zen_server/dashboard/assets/{index-CCOPpudF.js → index-FO-p0GU7.js} +5 -5
  112. zenml/zen_server/dashboard/assets/{index-B1mVPYxf.js → index-I3bKUGUj.js} +1 -1
  113. zenml/zen_server/dashboard/assets/key-icon-aH-QIa5R.js +1 -0
  114. zenml/zen_server/dashboard/assets/login-command-CkqxPtV3.js +1 -0
  115. zenml/zen_server/dashboard/assets/{login-mutation-hf-lK87O.js → login-mutation-BQeo4wTY.js} +1 -1
  116. zenml/zen_server/dashboard/assets/{not-found-BGirLjU-.js → not-found-gAJ5aDdR.js} +1 -1
  117. zenml/zen_server/dashboard/assets/page-9Y9-gig0.js +1 -0
  118. zenml/zen_server/dashboard/assets/{page-DjRJCGb3.js → page-AUwiQ14W.js} +1 -1
  119. zenml/zen_server/dashboard/assets/page-B6XU7yYT.js +2 -0
  120. zenml/zen_server/dashboard/assets/{page-C00YAkaB.js → page-BKZYc2Zv.js} +1 -1
  121. zenml/zen_server/dashboard/assets/{page-CdMWnQak.js → page-BU9FG4sR.js} +1 -1
  122. zenml/zen_server/dashboard/assets/{page-D7S3aCbF.js → page-B_Apk3xg.js} +1 -1
  123. zenml/zen_server/dashboard/assets/{page-Djikxq_S.js → page-BdowiCbr.js} +1 -1
  124. zenml/zen_server/dashboard/assets/page-Bg8OjTRe.js +1 -0
  125. zenml/zen_server/dashboard/assets/page-BxL4qD4_.js +1 -0
  126. zenml/zen_server/dashboard/assets/{page-DakHVWXF.js → page-CWxT5K5J.js} +1 -1
  127. zenml/zen_server/dashboard/assets/page-CXuQufSe.js +1 -0
  128. zenml/zen_server/dashboard/assets/{page-DLC-bNBP.js → page-CcQr8CPP.js} +1 -1
  129. zenml/zen_server/dashboard/assets/{page-CD-DcWoy.js → page-Ce4Hrjnr.js} +1 -1
  130. zenml/zen_server/dashboard/assets/page-CiYxgZP_.js +1 -0
  131. zenml/zen_server/dashboard/assets/page-Cldq1mpe.js +1 -0
  132. zenml/zen_server/dashboard/assets/{page-BDigxVpo.js → page-D4wdonLm.js} +1 -1
  133. zenml/zen_server/dashboard/assets/{page-D6uU2ax4.js → page-D8ObrbH8.js} +1 -1
  134. zenml/zen_server/dashboard/assets/{page-DXSTpqRD.js → page-DFuAUGt4.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{page-CbpvrsDL.js → page-DGazBpuP.js} +1 -1
  136. zenml/zen_server/dashboard/assets/{page-COXXJj1k.js → page-DO1UcqPX.js} +1 -1
  137. zenml/zen_server/dashboard/assets/page-DRYXdL5o.js +1 -0
  138. zenml/zen_server/dashboard/assets/{page-Df-Fw0aq.js → page-DYEquBC2.js} +1 -1
  139. zenml/zen_server/dashboard/assets/page-Dk32IeZm.js +1 -0
  140. zenml/zen_server/dashboard/assets/{page-yYC9OI-E.js → page-I3nKFGie.js} +1 -1
  141. zenml/zen_server/dashboard/assets/{page-6m6yHHlE.js → page-M0w-n6vn.js} +1 -1
  142. zenml/zen_server/dashboard/assets/{page-Vcxara9U.js → page-R5dx3xGF.js} +1 -1
  143. zenml/zen_server/dashboard/assets/{page-BR68V0V1.js → page-bT5pOvcB.js} +1 -1
  144. zenml/zen_server/dashboard/assets/page-hUqK889I.js +6 -0
  145. zenml/zen_server/dashboard/assets/{page-CjGdWY13.js → page-h_Stveon.js} +1 -1
  146. zenml/zen_server/dashboard/assets/{page-D01JhjQB.js → page-r8XK5vR7.js} +1 -1
  147. zenml/zen_server/dashboard/assets/page-u_-ZXBKb.js +1 -0
  148. zenml/zen_server/dashboard/assets/page-zaMqB_ao.js +1 -0
  149. zenml/zen_server/dashboard/assets/{persist-GjC8PZoC.js → persist-AppN1B0J.js} +1 -1
  150. zenml/zen_server/dashboard/assets/{persist-Coz7ZWvz.js → persist-DAUi_3za.js} +1 -1
  151. zenml/zen_server/dashboard/assets/service-BqqeXLEe.js +2 -0
  152. zenml/zen_server/dashboard/assets/{sharedSchema-CQb14VSr.js → sharedSchema-uXN9FLLk.js} +1 -1
  153. zenml/zen_server/dashboard/assets/{stack-detail-query-OPEW-cDJ.js → stack-detail-query-XfZBiBP2.js} +1 -1
  154. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-LwuQfHYn.js → update-server-settings-mutation-BWmgVJwA.js} +1 -1
  155. zenml/zen_server/dashboard/assets/{url-CkvKAnwF.js → url-BLwMbzES.js} +1 -1
  156. zenml/zen_server/dashboard/index.html +4 -4
  157. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  158. zenml/zen_server/deploy/helm/README.md +2 -2
  159. zenml/zen_server/rbac/rbac_sql_zen_store.py +173 -0
  160. zenml/zen_server/routers/auth_endpoints.py +22 -11
  161. zenml/zen_server/routers/steps_endpoints.py +7 -1
  162. zenml/zen_server/template_execution/utils.py +3 -1
  163. zenml/zen_server/utils.py +4 -3
  164. zenml/zen_stores/base_zen_store.py +10 -2
  165. zenml/zen_stores/migrations/versions/0.71.0_release.py +23 -0
  166. zenml/zen_stores/migrations/versions/26351d482b9e_add_step_run_unique_constraint.py +37 -0
  167. zenml/zen_stores/migrations/versions/a1237ba94fd8_add_model_version_producer_run_unique_.py +68 -0
  168. zenml/zen_stores/rest_zen_store.py +76 -43
  169. zenml/zen_stores/schemas/model_schemas.py +42 -6
  170. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +7 -7
  171. zenml/zen_stores/schemas/pipeline_run_schemas.py +12 -6
  172. zenml/zen_stores/schemas/pipeline_schemas.py +5 -0
  173. zenml/zen_stores/schemas/step_run_schemas.py +8 -1
  174. zenml/zen_stores/sql_zen_store.py +332 -100
  175. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/METADATA +5 -5
  176. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/RECORD +179 -164
  177. zenml/zen_server/dashboard/assets/RunSelector-DkPiIiNr.js +0 -1
  178. zenml/zen_server/dashboard/assets/StackList-WvuKQusZ.js +0 -1
  179. zenml/zen_server/dashboard/assets/delete-run-CJdh1P_h.js +0 -1
  180. zenml/zen_server/dashboard/assets/index-DlGvJQPn.css +0 -1
  181. zenml/zen_server/dashboard/assets/page-0JE_-Ec1.js +0 -1
  182. zenml/zen_server/dashboard/assets/page-BRLpxOt0.js +0 -1
  183. zenml/zen_server/dashboard/assets/page-BU7huvKw.js +0 -6
  184. zenml/zen_server/dashboard/assets/page-BvqLv2Ky.js +0 -1
  185. zenml/zen_server/dashboard/assets/page-CwxrFarU.js +0 -1
  186. zenml/zen_server/dashboard/assets/page-DfbXf_8s.js +0 -1
  187. zenml/zen_server/dashboard/assets/page-Dnovpa0i.js +0 -3
  188. zenml/zen_server/dashboard/assets/page-Dot3LPmL.js +0 -1
  189. zenml/zen_server/dashboard/assets/page-Xynx4btY.js +0 -14
  190. zenml/zen_server/dashboard/assets/page-YpKAqVSa.js +0 -1
  191. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/LICENSE +0 -0
  192. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/WHEEL +0 -0
  193. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/entry_points.txt +0 -0
@@ -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
@@ -793,7 +793,7 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
793
793
  "set or set to 0. The accelerator type will be ignored. "
794
794
  "To fix this warning, either remove the specified "
795
795
  "accelerator type or set the `gpu_count` using the "
796
- "ResourceSettings (https://docs.zenml.io/how-to/training-with-gpus#specify-resource-requirements-for-steps)."
796
+ "ResourceSettings (https://docs.zenml.io/how-to/advanced-topics/training-with-gpus)."
797
797
  )
798
798
 
799
799
  return dynamic_component
@@ -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, use_gzip=True)
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."""
@@ -33,7 +33,6 @@ from zenml.stack import Stack, StackValidator
33
33
  from zenml.step_operators import BaseStepOperator
34
34
 
35
35
  if TYPE_CHECKING:
36
- from zenml.config.base_settings import BaseSettings
37
36
  from zenml.config.step_run_info import StepRunInfo
38
37
  from zenml.models import PipelineDeploymentBase
39
38
 
@@ -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."""
@@ -77,10 +77,12 @@ class NeptuneExperimentTracker(BaseExperimentTracker):
77
77
  NeptuneExperimentTrackerSettings, self.get_settings(info)
78
78
  )
79
79
 
80
- self.run_state.token = self.config.api_token
81
- self.run_state.project = self.config.project
82
- self.run_state.run_name = info.run_name
83
- self.run_state.tags = list(settings.tags)
80
+ self.run_state.initialize(
81
+ project=self.config.project,
82
+ token=self.config.api_token,
83
+ run_name=info.run_name,
84
+ tags=list(settings.tags),
85
+ )
84
86
 
85
87
  def get_step_run_metadata(
86
88
  self, info: "StepRunInfo"
@@ -107,4 +109,4 @@ class NeptuneExperimentTracker(BaseExperimentTracker):
107
109
  """
108
110
  self.run_state.active_run.sync()
109
111
  self.run_state.active_run.stop()
110
- self.run_state.reset_active_run()
112
+ self.run_state.reset()