zenml-nightly 0.83.1.dev20250624__py3-none-any.whl → 0.83.1.dev20250626__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/cli/base.py +3 -2
- zenml/cli/login.py +21 -3
- zenml/cli/service_connectors.py +5 -12
- zenml/cli/stack.py +1 -5
- zenml/cli/utils.py +8 -52
- zenml/client.py +32 -40
- zenml/config/__init__.py +13 -2
- zenml/constants.py +0 -1
- zenml/exceptions.py +16 -0
- zenml/integrations/airflow/orchestrators/airflow_orchestrator.py +15 -6
- zenml/integrations/aws/container_registries/aws_container_registry.py +3 -1
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +54 -58
- zenml/integrations/azure/orchestrators/azureml_orchestrator.py +28 -19
- zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +19 -63
- zenml/integrations/databricks/orchestrators/databricks_orchestrator_entrypoint_config.py +8 -3
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +36 -61
- zenml/integrations/hyperai/orchestrators/hyperai_orchestrator.py +19 -22
- zenml/integrations/integration.py +23 -58
- zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +28 -31
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +33 -20
- zenml/integrations/lightning/orchestrators/lightning_orchestrator.py +25 -100
- zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +19 -8
- zenml/integrations/skypilot/utils.py +17 -13
- zenml/integrations/tekton/orchestrators/tekton_orchestrator.py +28 -12
- zenml/models/__init__.py +2 -0
- zenml/models/v2/core/service_connector.py +178 -108
- zenml/models/v2/core/step_run.py +1 -0
- zenml/orchestrators/__init__.py +2 -0
- zenml/orchestrators/base_orchestrator.py +137 -66
- zenml/orchestrators/input_utils.py +5 -13
- zenml/orchestrators/local/local_orchestrator.py +19 -9
- zenml/orchestrators/local_docker/local_docker_orchestrator.py +15 -5
- zenml/orchestrators/publish_utils.py +24 -0
- zenml/orchestrators/step_run_utils.py +1 -2
- zenml/pipelines/run_utils.py +12 -7
- zenml/service_connectors/service_connector.py +11 -61
- zenml/service_connectors/service_connector_utils.py +4 -2
- zenml/step_operators/step_operator_entrypoint_configuration.py +1 -1
- zenml/utils/package_utils.py +111 -1
- zenml/zen_server/routers/service_connectors_endpoints.py +7 -22
- zenml/zen_stores/migrations/versions/5bb25e95849c_add_internal_secrets.py +62 -0
- zenml/zen_stores/rest_zen_store.py +204 -132
- zenml/zen_stores/schemas/secret_schemas.py +5 -0
- zenml/zen_stores/schemas/service_connector_schemas.py +16 -14
- zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +4 -1
- zenml/zen_stores/sql_zen_store.py +241 -119
- zenml/zen_stores/zen_store_interface.py +9 -1
- {zenml_nightly-0.83.1.dev20250624.dist-info → zenml_nightly-0.83.1.dev20250626.dist-info}/METADATA +1 -1
- {zenml_nightly-0.83.1.dev20250624.dist-info → zenml_nightly-0.83.1.dev20250626.dist-info}/RECORD +53 -53
- zenml/utils/integration_utils.py +0 -34
- {zenml_nightly-0.83.1.dev20250624.dist-info → zenml_nightly-0.83.1.dev20250626.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.83.1.dev20250624.dist-info → zenml_nightly-0.83.1.dev20250626.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.83.1.dev20250624.dist-info → zenml_nightly-0.83.1.dev20250626.dist-info}/entry_points.txt +0 -0
zenml/utils/package_utils.py
CHANGED
@@ -13,10 +13,26 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Utility functions for the package."""
|
15
15
|
|
16
|
-
|
16
|
+
import sys
|
17
|
+
from typing import Dict, List, Optional, Union, cast
|
17
18
|
|
18
19
|
import requests
|
19
20
|
from packaging import version
|
21
|
+
from packaging.markers import default_environment
|
22
|
+
from packaging.requirements import Requirement
|
23
|
+
|
24
|
+
if sys.version_info < (3, 10):
|
25
|
+
from importlib_metadata import (
|
26
|
+
PackageNotFoundError,
|
27
|
+
distribution,
|
28
|
+
distributions,
|
29
|
+
)
|
30
|
+
else:
|
31
|
+
from importlib.metadata import (
|
32
|
+
PackageNotFoundError,
|
33
|
+
distribution,
|
34
|
+
distributions,
|
35
|
+
)
|
20
36
|
|
21
37
|
|
22
38
|
def is_latest_zenml_version() -> bool:
|
@@ -87,3 +103,97 @@ def clean_requirements(requirements: List[str]) -> List[str]:
|
|
87
103
|
):
|
88
104
|
cleaned[package] = req
|
89
105
|
return sorted(cleaned.values())
|
106
|
+
|
107
|
+
|
108
|
+
def requirement_installed(requirement: Union[str, Requirement]) -> bool:
|
109
|
+
"""Check if a requirement is installed.
|
110
|
+
|
111
|
+
Args:
|
112
|
+
requirement: A requirement string.
|
113
|
+
|
114
|
+
Returns:
|
115
|
+
True if the requirement is installed, False otherwise.
|
116
|
+
"""
|
117
|
+
if isinstance(requirement, str):
|
118
|
+
requirement = Requirement(requirement)
|
119
|
+
|
120
|
+
try:
|
121
|
+
dist = distribution(requirement.name)
|
122
|
+
except PackageNotFoundError:
|
123
|
+
return False
|
124
|
+
|
125
|
+
return requirement.specifier.contains(dist.version)
|
126
|
+
|
127
|
+
|
128
|
+
def get_dependencies(
|
129
|
+
requirement: Requirement, recursive: bool = False
|
130
|
+
) -> List[Requirement]:
|
131
|
+
"""Get the dependencies of a requirement.
|
132
|
+
|
133
|
+
Args:
|
134
|
+
requirement: A requirement string.
|
135
|
+
recursive: Whether to include recursive dependencies.
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
A list of requirements.
|
139
|
+
"""
|
140
|
+
dist = distribution(requirement.name)
|
141
|
+
marker_environment = cast(Dict[str, str], default_environment())
|
142
|
+
|
143
|
+
dependencies = []
|
144
|
+
|
145
|
+
for req in dist.requires or []:
|
146
|
+
parsed_req = Requirement(req)
|
147
|
+
|
148
|
+
if parsed_req.marker:
|
149
|
+
should_include = False
|
150
|
+
|
151
|
+
marker_environment["extra"] = ""
|
152
|
+
if parsed_req.marker.evaluate(environment=marker_environment):
|
153
|
+
should_include = True
|
154
|
+
|
155
|
+
if not should_include:
|
156
|
+
# Not required without extras, so check if it's required with
|
157
|
+
# any of the requested extras
|
158
|
+
for extra in requirement.extras:
|
159
|
+
marker_environment["extra"] = extra
|
160
|
+
if parsed_req.marker.evaluate(
|
161
|
+
environment=marker_environment
|
162
|
+
):
|
163
|
+
should_include = True
|
164
|
+
break
|
165
|
+
|
166
|
+
if should_include:
|
167
|
+
dependencies.append(parsed_req)
|
168
|
+
else:
|
169
|
+
# No marker means always include
|
170
|
+
dependencies.append(parsed_req)
|
171
|
+
|
172
|
+
if recursive:
|
173
|
+
for dependency in dependencies:
|
174
|
+
dependencies.extend(get_dependencies(dependency, recursive=True))
|
175
|
+
|
176
|
+
return dependencies
|
177
|
+
|
178
|
+
|
179
|
+
def get_package_information(
|
180
|
+
package_names: Optional[List[str]] = None,
|
181
|
+
) -> Dict[str, str]:
|
182
|
+
"""Get package information.
|
183
|
+
|
184
|
+
Args:
|
185
|
+
package_names: Filter for specific package names. If no package names
|
186
|
+
are provided, all installed packages are returned.
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
A dictionary of the name:version for the package names passed in or
|
190
|
+
all packages and their respective versions.
|
191
|
+
"""
|
192
|
+
if package_names:
|
193
|
+
return {
|
194
|
+
dist.name: dist.version
|
195
|
+
for dist in distributions()
|
196
|
+
if dist.name in package_names
|
197
|
+
}
|
198
|
+
|
199
|
+
return {dist.name: dist.version for dist in distributions()}
|
@@ -152,6 +152,7 @@ def list_service_connectors(
|
|
152
152
|
resource_type=ResourceType.SERVICE_CONNECTOR,
|
153
153
|
list_method=zen_store().list_service_connectors,
|
154
154
|
hydrate=hydrate,
|
155
|
+
expand_secrets=expand_secrets,
|
155
156
|
)
|
156
157
|
|
157
158
|
if expand_secrets:
|
@@ -163,9 +164,6 @@ def list_service_connectors(
|
|
163
164
|
)
|
164
165
|
|
165
166
|
for connector in connectors.items:
|
166
|
-
if not connector.secret_id:
|
167
|
-
continue
|
168
|
-
|
169
167
|
if allowed_ids is None or is_owned_by_authenticated_user(
|
170
168
|
connector
|
171
169
|
):
|
@@ -174,14 +172,8 @@ def list_service_connectors(
|
|
174
172
|
pass
|
175
173
|
elif connector.id not in allowed_ids:
|
176
174
|
# The user is not allowed to read secret values for this
|
177
|
-
# connector. We
|
178
|
-
|
179
|
-
continue
|
180
|
-
|
181
|
-
secret = zen_store().get_secret(secret_id=connector.secret_id)
|
182
|
-
|
183
|
-
# Update the connector configuration with the secret.
|
184
|
-
connector.configuration.update(secret.secret_values)
|
175
|
+
# connector. We remove the secrets from the connector.
|
176
|
+
connector.remove_secrets()
|
185
177
|
|
186
178
|
return connectors
|
187
179
|
|
@@ -253,21 +245,14 @@ def get_service_connector(
|
|
253
245
|
The requested service connector.
|
254
246
|
"""
|
255
247
|
connector = zen_store().get_service_connector(
|
256
|
-
connector_id, hydrate=hydrate
|
248
|
+
connector_id, hydrate=hydrate, expand_secrets=expand_secrets
|
257
249
|
)
|
258
250
|
verify_permission_for_model(connector, action=Action.READ)
|
259
251
|
|
260
|
-
if (
|
261
|
-
|
262
|
-
and connector.secret_id
|
263
|
-
and has_permissions_for_model(
|
264
|
-
connector, action=Action.READ_SECRET_VALUE
|
265
|
-
)
|
252
|
+
if expand_secrets and not has_permissions_for_model(
|
253
|
+
connector, action=Action.READ_SECRET_VALUE
|
266
254
|
):
|
267
|
-
|
268
|
-
|
269
|
-
# Update the connector configuration with the secret.
|
270
|
-
connector.configuration.update(secret.secret_values)
|
255
|
+
connector.remove_secrets()
|
271
256
|
|
272
257
|
return dehydrate_response_model(connector)
|
273
258
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
"""add internal secrets [5bb25e95849c].
|
2
|
+
|
3
|
+
Revision ID: 5bb25e95849c
|
4
|
+
Revises: 0.83.1
|
5
|
+
Create Date: 2025-06-23 20:49:44.184630
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
import sqlalchemy as sa
|
10
|
+
from alembic import op
|
11
|
+
|
12
|
+
# revision identifiers, used by Alembic.
|
13
|
+
revision = "5bb25e95849c"
|
14
|
+
down_revision = "0.83.1"
|
15
|
+
branch_labels = None
|
16
|
+
depends_on = None
|
17
|
+
|
18
|
+
|
19
|
+
def upgrade() -> None:
|
20
|
+
"""Upgrade database schema and/or data, creating a new revision."""
|
21
|
+
# Step 1: Add internal column as nullable
|
22
|
+
with op.batch_alter_table("secret", schema=None) as batch_op:
|
23
|
+
batch_op.add_column(sa.Column("internal", sa.Boolean(), nullable=True))
|
24
|
+
|
25
|
+
# Step 2: Update existing records based on service connector references
|
26
|
+
# If a secret is referenced by a service_connector.secret_id, make it internal=True
|
27
|
+
# Otherwise, set it to internal=False
|
28
|
+
connection = op.get_bind()
|
29
|
+
|
30
|
+
# Update secrets that are referenced by service connectors to be internal
|
31
|
+
connection.execute(
|
32
|
+
sa.text("""
|
33
|
+
UPDATE secret
|
34
|
+
SET internal = TRUE
|
35
|
+
WHERE id IN (
|
36
|
+
SELECT DISTINCT secret_id
|
37
|
+
FROM service_connector
|
38
|
+
WHERE secret_id IS NOT NULL
|
39
|
+
);
|
40
|
+
""")
|
41
|
+
)
|
42
|
+
|
43
|
+
# Update all other secrets to be not internal
|
44
|
+
connection.execute(
|
45
|
+
sa.text("""
|
46
|
+
UPDATE secret
|
47
|
+
SET internal = FALSE
|
48
|
+
WHERE internal IS NULL;
|
49
|
+
""")
|
50
|
+
)
|
51
|
+
|
52
|
+
# Step 3: Make internal column non-nullable
|
53
|
+
with op.batch_alter_table("secret", schema=None) as batch_op:
|
54
|
+
batch_op.alter_column(
|
55
|
+
"internal", existing_type=sa.Boolean(), nullable=False
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
def downgrade() -> None:
|
60
|
+
"""Downgrade database schema and/or data back to the previous revision."""
|
61
|
+
with op.batch_alter_table("secret", schema=None) as batch_op:
|
62
|
+
batch_op.drop_column("internal")
|