mlrun 1.10.0rc18__py3-none-any.whl → 1.11.0rc16__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.
Potentially problematic release.
This version of mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +24 -3
- mlrun/__main__.py +0 -4
- mlrun/artifacts/dataset.py +2 -2
- mlrun/artifacts/document.py +6 -1
- mlrun/artifacts/llm_prompt.py +21 -15
- mlrun/artifacts/model.py +3 -3
- mlrun/artifacts/plots.py +1 -1
- mlrun/{model_monitoring/db/tsdb/tdengine → auth}/__init__.py +2 -3
- mlrun/auth/nuclio.py +89 -0
- mlrun/auth/providers.py +429 -0
- mlrun/auth/utils.py +415 -0
- mlrun/common/constants.py +14 -0
- mlrun/common/model_monitoring/helpers.py +123 -0
- mlrun/common/runtimes/constants.py +28 -0
- mlrun/common/schemas/__init__.py +14 -3
- mlrun/common/schemas/alert.py +2 -2
- mlrun/common/schemas/api_gateway.py +3 -0
- mlrun/common/schemas/auth.py +12 -10
- mlrun/common/schemas/client_spec.py +4 -0
- mlrun/common/schemas/constants.py +25 -0
- mlrun/common/schemas/frontend_spec.py +1 -8
- mlrun/common/schemas/function.py +34 -0
- mlrun/common/schemas/hub.py +33 -20
- mlrun/common/schemas/model_monitoring/__init__.py +2 -1
- mlrun/common/schemas/model_monitoring/constants.py +12 -15
- mlrun/common/schemas/model_monitoring/functions.py +13 -4
- mlrun/common/schemas/model_monitoring/model_endpoints.py +11 -0
- mlrun/common/schemas/pipeline.py +1 -1
- mlrun/common/schemas/secret.py +17 -2
- mlrun/common/secrets.py +95 -1
- mlrun/common/types.py +10 -10
- mlrun/config.py +69 -19
- mlrun/data_types/infer.py +2 -2
- mlrun/datastore/__init__.py +12 -5
- mlrun/datastore/azure_blob.py +162 -47
- mlrun/datastore/base.py +274 -10
- mlrun/datastore/datastore.py +7 -2
- mlrun/datastore/datastore_profile.py +84 -22
- mlrun/datastore/model_provider/huggingface_provider.py +225 -41
- mlrun/datastore/model_provider/mock_model_provider.py +87 -0
- mlrun/datastore/model_provider/model_provider.py +206 -74
- mlrun/datastore/model_provider/openai_provider.py +226 -66
- mlrun/datastore/s3.py +39 -18
- mlrun/datastore/sources.py +1 -1
- mlrun/datastore/store_resources.py +4 -4
- mlrun/datastore/storeytargets.py +17 -12
- mlrun/datastore/targets.py +1 -1
- mlrun/datastore/utils.py +25 -6
- mlrun/datastore/v3io.py +1 -1
- mlrun/db/base.py +63 -32
- mlrun/db/httpdb.py +373 -153
- mlrun/db/nopdb.py +54 -21
- mlrun/errors.py +4 -2
- mlrun/execution.py +66 -25
- mlrun/feature_store/api.py +1 -1
- mlrun/feature_store/common.py +1 -1
- mlrun/feature_store/feature_vector_utils.py +1 -1
- mlrun/feature_store/steps.py +8 -6
- mlrun/frameworks/_common/utils.py +3 -3
- mlrun/frameworks/_dl_common/loggers/logger.py +1 -1
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +2 -1
- mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +1 -1
- mlrun/frameworks/_ml_common/utils.py +2 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +4 -3
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +2 -1
- mlrun/frameworks/onnx/dataset.py +2 -1
- mlrun/frameworks/onnx/mlrun_interface.py +2 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +5 -4
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +2 -1
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +2 -1
- mlrun/frameworks/pytorch/utils.py +2 -1
- mlrun/frameworks/sklearn/metric.py +2 -1
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +5 -4
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +2 -1
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +2 -1
- mlrun/hub/__init__.py +52 -0
- mlrun/hub/base.py +142 -0
- mlrun/hub/module.py +172 -0
- mlrun/hub/step.py +113 -0
- mlrun/k8s_utils.py +105 -16
- mlrun/launcher/base.py +15 -7
- mlrun/launcher/local.py +4 -1
- mlrun/model.py +14 -4
- mlrun/model_monitoring/__init__.py +0 -1
- mlrun/model_monitoring/api.py +65 -28
- mlrun/model_monitoring/applications/__init__.py +1 -1
- mlrun/model_monitoring/applications/base.py +299 -128
- mlrun/model_monitoring/applications/context.py +2 -4
- mlrun/model_monitoring/controller.py +132 -58
- mlrun/model_monitoring/db/_schedules.py +38 -29
- mlrun/model_monitoring/db/_stats.py +6 -16
- mlrun/model_monitoring/db/tsdb/__init__.py +9 -7
- mlrun/model_monitoring/db/tsdb/base.py +29 -9
- mlrun/model_monitoring/db/tsdb/preaggregate.py +234 -0
- mlrun/model_monitoring/db/tsdb/stream_graph_steps.py +63 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_metrics_queries.py +414 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_predictions_queries.py +376 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_results_queries.py +590 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_connection.py +434 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_connector.py +541 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_operations.py +808 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_schema.py +502 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_stream.py +163 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_stream_graph_steps.py +60 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/utils/timescaledb_dataframe_processor.py +141 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/utils/timescaledb_query_builder.py +585 -0
- mlrun/model_monitoring/db/tsdb/timescaledb/writer_graph_steps.py +73 -0
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +20 -9
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +235 -51
- mlrun/model_monitoring/features_drift_table.py +2 -1
- mlrun/model_monitoring/helpers.py +30 -6
- mlrun/model_monitoring/stream_processing.py +34 -28
- mlrun/model_monitoring/writer.py +224 -4
- mlrun/package/__init__.py +2 -1
- mlrun/platforms/__init__.py +0 -43
- mlrun/platforms/iguazio.py +8 -4
- mlrun/projects/operations.py +17 -11
- mlrun/projects/pipelines.py +2 -2
- mlrun/projects/project.py +187 -123
- mlrun/run.py +95 -21
- mlrun/runtimes/__init__.py +2 -186
- mlrun/runtimes/base.py +103 -25
- mlrun/runtimes/constants.py +225 -0
- mlrun/runtimes/daskjob.py +5 -2
- mlrun/runtimes/databricks_job/databricks_runtime.py +2 -1
- mlrun/runtimes/local.py +5 -2
- mlrun/runtimes/mounts.py +20 -2
- mlrun/runtimes/nuclio/__init__.py +12 -7
- mlrun/runtimes/nuclio/api_gateway.py +36 -6
- mlrun/runtimes/nuclio/application/application.py +339 -40
- mlrun/runtimes/nuclio/function.py +222 -72
- mlrun/runtimes/nuclio/serving.py +132 -42
- mlrun/runtimes/pod.py +213 -21
- mlrun/runtimes/utils.py +49 -9
- mlrun/secrets.py +99 -14
- mlrun/serving/__init__.py +2 -0
- mlrun/serving/remote.py +84 -11
- mlrun/serving/routers.py +26 -44
- mlrun/serving/server.py +138 -51
- mlrun/serving/serving_wrapper.py +6 -2
- mlrun/serving/states.py +997 -283
- mlrun/serving/steps.py +62 -0
- mlrun/serving/system_steps.py +149 -95
- mlrun/serving/v2_serving.py +9 -10
- mlrun/track/trackers/mlflow_tracker.py +29 -31
- mlrun/utils/helpers.py +292 -94
- mlrun/utils/http.py +9 -2
- mlrun/utils/notifications/notification/base.py +18 -0
- mlrun/utils/notifications/notification/git.py +3 -5
- mlrun/utils/notifications/notification/mail.py +39 -16
- mlrun/utils/notifications/notification/slack.py +2 -4
- mlrun/utils/notifications/notification/webhook.py +2 -5
- mlrun/utils/notifications/notification_pusher.py +3 -3
- mlrun/utils/version/version.json +2 -2
- mlrun/utils/version/version.py +3 -4
- {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/METADATA +63 -74
- {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/RECORD +161 -143
- mlrun/api/schemas/__init__.py +0 -259
- mlrun/db/auth_utils.py +0 -152
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +0 -344
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +0 -75
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py +0 -281
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +0 -1266
- {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/WHEEL +0 -0
- {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/entry_points.txt +0 -0
- {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/licenses/LICENSE +0 -0
- {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
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
|
+
# http://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 or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import typing
|
|
16
|
+
|
|
17
|
+
import mlrun.runtimes.nuclio as nuclio_runtime
|
|
18
|
+
import mlrun.runtimes.nuclio.application as nuclio_application
|
|
19
|
+
import mlrun.runtimes.nuclio.serving as nuclio_serving
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RuntimeKinds:
|
|
23
|
+
remote = "remote"
|
|
24
|
+
nuclio = "nuclio"
|
|
25
|
+
dask = "dask"
|
|
26
|
+
job = "job"
|
|
27
|
+
spark = "spark"
|
|
28
|
+
remotespark = "remote-spark"
|
|
29
|
+
mpijob = "mpijob"
|
|
30
|
+
serving = "serving"
|
|
31
|
+
local = "local"
|
|
32
|
+
handler = "handler"
|
|
33
|
+
databricks = "databricks"
|
|
34
|
+
application = "application"
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def all():
|
|
38
|
+
return [
|
|
39
|
+
RuntimeKinds.remote,
|
|
40
|
+
RuntimeKinds.nuclio,
|
|
41
|
+
RuntimeKinds.serving,
|
|
42
|
+
RuntimeKinds.dask,
|
|
43
|
+
RuntimeKinds.job,
|
|
44
|
+
RuntimeKinds.spark,
|
|
45
|
+
RuntimeKinds.remotespark,
|
|
46
|
+
RuntimeKinds.mpijob,
|
|
47
|
+
RuntimeKinds.local,
|
|
48
|
+
RuntimeKinds.databricks,
|
|
49
|
+
RuntimeKinds.application,
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def runtime_with_handlers():
|
|
54
|
+
return [
|
|
55
|
+
RuntimeKinds.dask,
|
|
56
|
+
RuntimeKinds.job,
|
|
57
|
+
RuntimeKinds.spark,
|
|
58
|
+
RuntimeKinds.remotespark,
|
|
59
|
+
RuntimeKinds.mpijob,
|
|
60
|
+
RuntimeKinds.databricks,
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
@staticmethod
|
|
64
|
+
def abortable_runtimes():
|
|
65
|
+
return [
|
|
66
|
+
RuntimeKinds.job,
|
|
67
|
+
RuntimeKinds.spark,
|
|
68
|
+
RuntimeKinds.remotespark,
|
|
69
|
+
RuntimeKinds.mpijob,
|
|
70
|
+
RuntimeKinds.databricks,
|
|
71
|
+
RuntimeKinds.local,
|
|
72
|
+
RuntimeKinds.handler,
|
|
73
|
+
"",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def retriable_runtimes():
|
|
78
|
+
return [
|
|
79
|
+
RuntimeKinds.job,
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def nuclio_runtimes():
|
|
84
|
+
return [
|
|
85
|
+
RuntimeKinds.remote,
|
|
86
|
+
RuntimeKinds.nuclio,
|
|
87
|
+
RuntimeKinds.serving,
|
|
88
|
+
RuntimeKinds.application,
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def pure_nuclio_deployed_runtimes():
|
|
93
|
+
return [
|
|
94
|
+
RuntimeKinds.remote,
|
|
95
|
+
RuntimeKinds.nuclio,
|
|
96
|
+
RuntimeKinds.serving,
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
@staticmethod
|
|
100
|
+
def handlerless_runtimes():
|
|
101
|
+
return [
|
|
102
|
+
RuntimeKinds.serving,
|
|
103
|
+
# Application runtime handler is internal reverse proxy
|
|
104
|
+
RuntimeKinds.application,
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
@staticmethod
|
|
108
|
+
def local_runtimes():
|
|
109
|
+
return [
|
|
110
|
+
RuntimeKinds.local,
|
|
111
|
+
RuntimeKinds.handler,
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def is_log_collectable_runtime(kind: typing.Optional[str]):
|
|
116
|
+
"""
|
|
117
|
+
whether log collector can collect logs for that runtime
|
|
118
|
+
:param kind: kind name
|
|
119
|
+
:return: whether log collector can collect logs for that runtime
|
|
120
|
+
"""
|
|
121
|
+
# if local run, the log collector doesn't support it as it is only supports k8s resources
|
|
122
|
+
# when runtime is local the client is responsible for logging the stdout of the run by using `log_std`
|
|
123
|
+
if RuntimeKinds.is_local_runtime(kind):
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
if (
|
|
127
|
+
kind
|
|
128
|
+
not in [
|
|
129
|
+
# dask implementation is different from other runtimes, because few runs can be run against the same
|
|
130
|
+
# runtime resource, so collecting logs on that runtime resource won't be correct, the way we collect
|
|
131
|
+
# logs for dask is by using `log_std` on client side after we execute the code against the cluster,
|
|
132
|
+
# as submitting the run with the dask client will return the run stdout.
|
|
133
|
+
# For more information head to `DaskCluster._run`.
|
|
134
|
+
RuntimeKinds.dask
|
|
135
|
+
]
|
|
136
|
+
+ RuntimeKinds.nuclio_runtimes()
|
|
137
|
+
):
|
|
138
|
+
return True
|
|
139
|
+
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
def is_local_runtime(kind):
|
|
144
|
+
# "" or None counted as local
|
|
145
|
+
if not kind or kind in RuntimeKinds.local_runtimes():
|
|
146
|
+
return True
|
|
147
|
+
return False
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def requires_k8s_name_validation(kind: str) -> bool:
|
|
151
|
+
"""
|
|
152
|
+
Returns True if the runtime kind creates Kubernetes resources that use the function name.
|
|
153
|
+
|
|
154
|
+
Function names for k8s-deployed runtimes must conform to DNS-1123 label requirements:
|
|
155
|
+
- Lowercase alphanumeric characters or '-'
|
|
156
|
+
- Start and end with an alphanumeric character
|
|
157
|
+
- Maximum 63 characters
|
|
158
|
+
|
|
159
|
+
Local runtimes (local, handler) run on the local machine and don't create k8s resources,
|
|
160
|
+
so they don't require k8s naming validation.
|
|
161
|
+
|
|
162
|
+
:param kind: Runtime kind string (job, spark, serving, local, etc.)
|
|
163
|
+
:return: True if function name needs k8s DNS-1123 validation, False otherwise
|
|
164
|
+
"""
|
|
165
|
+
return not RuntimeKinds.is_local_runtime(kind)
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
def requires_absolute_artifacts_path(kind):
|
|
169
|
+
"""
|
|
170
|
+
Returns True if the runtime kind requires absolute artifacts' path (i.e. is local), False otherwise.
|
|
171
|
+
"""
|
|
172
|
+
if RuntimeKinds.is_local_runtime(kind):
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
if kind not in [
|
|
176
|
+
# logging artifacts is done externally to the dask cluster by a client that can either run locally (in which
|
|
177
|
+
# case the path can be relative) or remotely (in which case the path must be absolute and will be passed
|
|
178
|
+
# to another run)
|
|
179
|
+
RuntimeKinds.dask
|
|
180
|
+
]:
|
|
181
|
+
return True
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
@staticmethod
|
|
185
|
+
def requires_image_name_for_execution(kind):
|
|
186
|
+
if RuntimeKinds.is_local_runtime(kind):
|
|
187
|
+
return False
|
|
188
|
+
|
|
189
|
+
# both spark and remote spark uses different mechanism for assigning images
|
|
190
|
+
return kind not in [RuntimeKinds.spark, RuntimeKinds.remotespark]
|
|
191
|
+
|
|
192
|
+
@staticmethod
|
|
193
|
+
def supports_from_notebook(kind):
|
|
194
|
+
return kind not in [RuntimeKinds.application]
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def resolve_nuclio_runtime(kind: str, sub_kind: str):
|
|
198
|
+
kind = kind.split(":")[0]
|
|
199
|
+
if kind not in RuntimeKinds.nuclio_runtimes():
|
|
200
|
+
raise ValueError(
|
|
201
|
+
f"Kind {kind} is not a nuclio runtime, "
|
|
202
|
+
f"available runtimes are {RuntimeKinds.nuclio_runtimes()}"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# These names are imported at module level below; referenced at call-time (no imports here).
|
|
206
|
+
if sub_kind == nuclio_serving.serving_subkind:
|
|
207
|
+
return nuclio_runtime.ServingRuntime()
|
|
208
|
+
|
|
209
|
+
if kind == RuntimeKinds.application:
|
|
210
|
+
return nuclio_application.ApplicationRuntime()
|
|
211
|
+
|
|
212
|
+
runtime = nuclio_runtime.RemoteRuntime()
|
|
213
|
+
runtime.spec.function_kind = sub_kind
|
|
214
|
+
return runtime
|
|
215
|
+
|
|
216
|
+
@staticmethod
|
|
217
|
+
def resolve_nuclio_sub_kind(kind: str):
|
|
218
|
+
is_nuclio = kind.startswith("nuclio")
|
|
219
|
+
sub_kind = kind[kind.find(":") + 1 :] if is_nuclio and ":" in kind else None
|
|
220
|
+
if kind == RuntimeKinds.serving:
|
|
221
|
+
is_nuclio = True
|
|
222
|
+
sub_kind = nuclio_serving.serving_subkind
|
|
223
|
+
elif kind == RuntimeKinds.application:
|
|
224
|
+
is_nuclio = True
|
|
225
|
+
return is_nuclio, sub_kind
|
mlrun/runtimes/daskjob.py
CHANGED
|
@@ -15,8 +15,9 @@ import datetime
|
|
|
15
15
|
import inspect
|
|
16
16
|
import socket
|
|
17
17
|
import time
|
|
18
|
+
from collections.abc import Callable
|
|
18
19
|
from os import environ
|
|
19
|
-
from typing import
|
|
20
|
+
from typing import Optional, Union
|
|
20
21
|
|
|
21
22
|
import mlrun.common.schemas
|
|
22
23
|
import mlrun.errors
|
|
@@ -541,6 +542,7 @@ class DaskCluster(KubejobRuntime):
|
|
|
541
542
|
notifications=notifications,
|
|
542
543
|
returns=returns,
|
|
543
544
|
state_thresholds=state_thresholds,
|
|
545
|
+
retry=retry,
|
|
544
546
|
**launcher_kwargs,
|
|
545
547
|
)
|
|
546
548
|
|
|
@@ -550,7 +552,8 @@ class DaskCluster(KubejobRuntime):
|
|
|
550
552
|
|
|
551
553
|
# TODO: investigate if the following instructions could overwrite the environment on any MLRun API Pod
|
|
552
554
|
# Such action could result on race conditions against other runtimes and MLRun itself
|
|
553
|
-
extra_env = self._generate_runtime_env(runobj)
|
|
555
|
+
extra_env, _ = self._generate_runtime_env(runobj)
|
|
556
|
+
# Since it runs locally, we don't need the external sources env vars
|
|
554
557
|
environ.update(extra_env)
|
|
555
558
|
|
|
556
559
|
context = MLClientCtx.from_dict(
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
import typing
|
|
15
15
|
from ast import FunctionDef, parse, unparse
|
|
16
16
|
from base64 import b64decode
|
|
17
|
-
from
|
|
17
|
+
from collections.abc import Callable
|
|
18
|
+
from typing import Optional, Union
|
|
18
19
|
|
|
19
20
|
import mlrun
|
|
20
21
|
import mlrun.runtimes.kubejob as kubejob
|
mlrun/runtimes/local.py
CHANGED
|
@@ -29,12 +29,12 @@ from os import environ, remove
|
|
|
29
29
|
from pathlib import Path
|
|
30
30
|
from subprocess import PIPE, Popen
|
|
31
31
|
from sys import executable
|
|
32
|
+
from typing import Optional
|
|
32
33
|
|
|
33
34
|
from nuclio import Event
|
|
34
35
|
|
|
35
36
|
import mlrun
|
|
36
37
|
import mlrun.common.constants as mlrun_constants
|
|
37
|
-
import mlrun.common.runtimes.constants
|
|
38
38
|
from mlrun.lists import RunList
|
|
39
39
|
|
|
40
40
|
from ..errors import err_to_str
|
|
@@ -201,9 +201,12 @@ class LocalRuntime(BaseRuntime, ParallelRunner):
|
|
|
201
201
|
kind = "local"
|
|
202
202
|
_is_remote = False
|
|
203
203
|
|
|
204
|
-
def to_job(self, image=""):
|
|
204
|
+
def to_job(self, image="", func_name: Optional[str] = None):
|
|
205
205
|
struct = self.to_dict()
|
|
206
206
|
obj = KubejobRuntime.from_dict(struct)
|
|
207
|
+
obj.kind = "job" # Ensure kind is set to 'job' for KubejobRuntime
|
|
208
|
+
if func_name:
|
|
209
|
+
obj.metadata.name = func_name
|
|
207
210
|
if image:
|
|
208
211
|
obj.spec.image = image
|
|
209
212
|
return obj
|
mlrun/runtimes/mounts.py
CHANGED
|
@@ -14,8 +14,11 @@
|
|
|
14
14
|
|
|
15
15
|
import os
|
|
16
16
|
import typing
|
|
17
|
+
import warnings
|
|
17
18
|
from collections import namedtuple
|
|
18
19
|
|
|
20
|
+
import mlrun.common.secrets
|
|
21
|
+
import mlrun.errors
|
|
19
22
|
from mlrun.config import config
|
|
20
23
|
from mlrun.config import config as mlconf
|
|
21
24
|
from mlrun.errors import MLRunInvalidArgumentError
|
|
@@ -247,10 +250,22 @@ def mount_s3(
|
|
|
247
250
|
def _use_s3_cred(runtime: "KubeResource"):
|
|
248
251
|
_access_key = aws_access_key or os.environ.get(prefix + "AWS_ACCESS_KEY_ID")
|
|
249
252
|
_secret_key = aws_secret_key or os.environ.get(prefix + "AWS_SECRET_ACCESS_KEY")
|
|
250
|
-
|
|
253
|
+
|
|
254
|
+
# Check for endpoint URL with backward compatibility
|
|
255
|
+
_endpoint_url = endpoint_url or os.environ.get(prefix + "AWS_ENDPOINT_URL_S3")
|
|
256
|
+
if not _endpoint_url:
|
|
257
|
+
# Check for deprecated environment variable
|
|
258
|
+
_endpoint_url = os.environ.get(prefix + "S3_ENDPOINT_URL")
|
|
259
|
+
if _endpoint_url:
|
|
260
|
+
warnings.warn(
|
|
261
|
+
"S3_ENDPOINT_URL is deprecated in 1.10.0 and will be removed in 1.12.0, "
|
|
262
|
+
"use AWS_ENDPOINT_URL_S3 instead.",
|
|
263
|
+
# TODO: Remove this in 1.12.0
|
|
264
|
+
FutureWarning,
|
|
265
|
+
)
|
|
251
266
|
|
|
252
267
|
if _endpoint_url:
|
|
253
|
-
runtime.set_env(prefix + "
|
|
268
|
+
runtime.set_env(prefix + "AWS_ENDPOINT_URL_S3", _endpoint_url)
|
|
254
269
|
if aws_region:
|
|
255
270
|
runtime.set_env(prefix + "AWS_REGION", aws_region)
|
|
256
271
|
if non_anonymous:
|
|
@@ -399,6 +414,9 @@ def mount_secret(
|
|
|
399
414
|
the specified paths, and unlisted keys will not be
|
|
400
415
|
present."""
|
|
401
416
|
|
|
417
|
+
if secret_name:
|
|
418
|
+
mlrun.common.secrets.validate_not_forbidden_secret(secret_name.strip())
|
|
419
|
+
|
|
402
420
|
def _mount_secret(runtime: "KubeResource"):
|
|
403
421
|
# Define the secret volume source
|
|
404
422
|
secret_volume_source = {
|
|
@@ -12,10 +12,15 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
import mlrun.runtimes.nuclio.serving as nuclio_serving # noqa
|
|
16
|
+
import mlrun.runtimes.nuclio.nuclio as nuclio_nuclio # noqa
|
|
17
|
+
import mlrun.runtimes.nuclio.function as nuclio_function # noqa
|
|
18
|
+
import mlrun.runtimes.nuclio.api_gateway as nuclio_api_gateway # noqa
|
|
19
|
+
|
|
20
|
+
ServingRuntime = nuclio_serving.ServingRuntime
|
|
21
|
+
new_v2_model_server = nuclio_serving.new_v2_model_server
|
|
22
|
+
nuclio_init_hook = nuclio_nuclio.nuclio_init_hook
|
|
23
|
+
min_nuclio_versions = nuclio_function.min_nuclio_versions
|
|
24
|
+
multiple_port_sidecar_is_supported = nuclio_function.multiple_port_sidecar_is_supported
|
|
25
|
+
RemoteRuntime = nuclio_function.RemoteRuntime
|
|
26
|
+
APIGateway = nuclio_api_gateway.APIGateway
|
|
@@ -17,13 +17,14 @@ from typing import Optional, Union
|
|
|
17
17
|
from urllib.parse import urljoin
|
|
18
18
|
|
|
19
19
|
import requests
|
|
20
|
-
from nuclio.auth import AuthInfo as NuclioAuthInfo
|
|
21
20
|
from nuclio.auth import AuthKinds as NuclioAuthKinds
|
|
22
21
|
|
|
23
22
|
import mlrun
|
|
23
|
+
import mlrun.auth.nuclio
|
|
24
24
|
import mlrun.common.constants as mlrun_constants
|
|
25
25
|
import mlrun.common.helpers
|
|
26
26
|
import mlrun.common.schemas as schemas
|
|
27
|
+
import mlrun.common.schemas.auth
|
|
27
28
|
import mlrun.common.types
|
|
28
29
|
from mlrun.model import ModelObj
|
|
29
30
|
from mlrun.platforms.iguazio import min_iguazio_versions
|
|
@@ -55,6 +56,11 @@ class Authenticator(typing.Protocol):
|
|
|
55
56
|
== schemas.APIGatewayAuthenticationMode.access_key.value
|
|
56
57
|
):
|
|
57
58
|
return AccessKeyAuth()
|
|
59
|
+
elif (
|
|
60
|
+
api_gateway_spec.authenticationMode
|
|
61
|
+
== schemas.APIGatewayAuthenticationMode.iguazio.value
|
|
62
|
+
):
|
|
63
|
+
return IguazioAuth()
|
|
58
64
|
else:
|
|
59
65
|
return NoneAuth()
|
|
60
66
|
|
|
@@ -112,6 +118,16 @@ class AccessKeyAuth(APIGatewayAuthenticator):
|
|
|
112
118
|
return schemas.APIGatewayAuthenticationMode.access_key.value
|
|
113
119
|
|
|
114
120
|
|
|
121
|
+
class IguazioAuth(APIGatewayAuthenticator):
|
|
122
|
+
"""
|
|
123
|
+
An API gateway authenticator with Iguazio authentication.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def authentication_mode(self) -> str:
|
|
128
|
+
return schemas.APIGatewayAuthenticationMode.iguazio.value
|
|
129
|
+
|
|
130
|
+
|
|
115
131
|
class APIGatewayMetadata(ModelObj):
|
|
116
132
|
_dict_fields = ["name", "namespace", "labels", "annotations", "creation_timestamp"]
|
|
117
133
|
|
|
@@ -430,7 +446,7 @@ class APIGateway(ModelObj):
|
|
|
430
446
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
431
447
|
"API Gateway invocation requires authentication. Please pass credentials"
|
|
432
448
|
)
|
|
433
|
-
auth = NuclioAuthInfo(
|
|
449
|
+
auth = mlrun.auth.nuclio.NuclioAuthInfo(
|
|
434
450
|
username=credentials[0], password=credentials[1]
|
|
435
451
|
).to_requests_auth()
|
|
436
452
|
|
|
@@ -440,23 +456,30 @@ class APIGateway(ModelObj):
|
|
|
440
456
|
):
|
|
441
457
|
# inject access key from env
|
|
442
458
|
if credentials:
|
|
443
|
-
auth = NuclioAuthInfo(
|
|
459
|
+
auth = mlrun.auth.nuclio.NuclioAuthInfo(
|
|
444
460
|
username=credentials[0],
|
|
445
461
|
password=credentials[1],
|
|
446
462
|
mode=NuclioAuthKinds.iguazio,
|
|
447
463
|
).to_requests_auth()
|
|
448
464
|
else:
|
|
449
|
-
auth =
|
|
465
|
+
auth = (
|
|
466
|
+
mlrun.auth.nuclio.NuclioAuthInfo().from_envvar().to_requests_auth()
|
|
467
|
+
)
|
|
450
468
|
if not auth:
|
|
451
469
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
452
470
|
"API Gateway invocation requires authentication. Please set V3IO_ACCESS_KEY env var"
|
|
453
471
|
)
|
|
472
|
+
if (
|
|
473
|
+
self.spec.authentication.authentication_mode
|
|
474
|
+
== schemas.APIGatewayAuthenticationMode.iguazio.value
|
|
475
|
+
):
|
|
476
|
+
auth = mlrun.auth.nuclio.NuclioAuthInfo.from_envvar().to_requests_auth()
|
|
454
477
|
url = urljoin(self.invoke_url, path or "")
|
|
455
478
|
|
|
456
479
|
# Determine the correct keyword argument for the body
|
|
457
480
|
if isinstance(body, dict):
|
|
458
481
|
kwargs["json"] = body
|
|
459
|
-
elif isinstance(body,
|
|
482
|
+
elif isinstance(body, str | bytes):
|
|
460
483
|
kwargs["data"] = body
|
|
461
484
|
|
|
462
485
|
return requests.request(
|
|
@@ -527,6 +550,13 @@ class APIGateway(ModelObj):
|
|
|
527
550
|
"""
|
|
528
551
|
self.spec.authentication = AccessKeyAuth()
|
|
529
552
|
|
|
553
|
+
@min_nuclio_versions("1.15.10")
|
|
554
|
+
def with_iguazio_auth(self):
|
|
555
|
+
"""
|
|
556
|
+
Set iguazio authentication for the API gateway.
|
|
557
|
+
"""
|
|
558
|
+
self.spec.authentication = IguazioAuth()
|
|
559
|
+
|
|
530
560
|
def with_canary(
|
|
531
561
|
self,
|
|
532
562
|
functions: Union[
|
|
@@ -692,7 +722,7 @@ class APIGateway(ModelObj):
|
|
|
692
722
|
@staticmethod
|
|
693
723
|
def _generate_basic_auth(username: str, password: str):
|
|
694
724
|
token = base64.b64encode(f"{username}:{password}".encode()).decode()
|
|
695
|
-
return f"
|
|
725
|
+
return f"{mlrun.common.schemas.AuthorizationHeaderPrefixes.basic}{token}"
|
|
696
726
|
|
|
697
727
|
@staticmethod
|
|
698
728
|
def _resolve_canary(
|