mlrun 1.10.0rc1__py3-none-any.whl → 1.10.0rc2__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/__main__.py +13 -2
- mlrun/common/constants.py +7 -0
- mlrun/common/runtimes/constants.py +8 -1
- mlrun/common/schemas/__init__.py +1 -0
- mlrun/common/schemas/serving.py +17 -0
- mlrun/datastore/datastore_profile.py +5 -55
- mlrun/datastore/sources.py +21 -13
- mlrun/datastore/utils.py +19 -4
- mlrun/db/base.py +1 -1
- mlrun/db/httpdb.py +22 -10
- mlrun/db/nopdb.py +1 -1
- mlrun/errors.py +7 -0
- mlrun/execution.py +9 -0
- mlrun/launcher/client.py +1 -1
- mlrun/model_monitoring/applications/evidently/base.py +59 -71
- mlrun/model_monitoring/controller.py +26 -13
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +13 -5
- mlrun/projects/project.py +95 -33
- mlrun/render.py +5 -9
- mlrun/runtimes/base.py +1 -1
- mlrun/runtimes/utils.py +25 -8
- mlrun/serving/states.py +142 -9
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/METADATA +8 -8
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/RECORD +29 -29
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/WHEEL +1 -1
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/entry_points.txt +0 -0
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/licenses/LICENSE +0 -0
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/top_level.txt +0 -0
mlrun/__main__.py
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
14
|
# See the License for the specific language governing permissions and
|
|
15
15
|
# limitations under the License.
|
|
16
|
+
import functools
|
|
17
|
+
import importlib.metadata
|
|
16
18
|
import json
|
|
17
19
|
import pathlib
|
|
18
20
|
import socket
|
|
@@ -25,12 +27,14 @@ from pprint import pprint
|
|
|
25
27
|
import click
|
|
26
28
|
import dotenv
|
|
27
29
|
import pandas as pd
|
|
30
|
+
import semver
|
|
28
31
|
import yaml
|
|
29
32
|
from tabulate import tabulate
|
|
30
33
|
|
|
31
34
|
import mlrun
|
|
32
35
|
import mlrun.common.constants as mlrun_constants
|
|
33
36
|
import mlrun.common.schemas
|
|
37
|
+
import mlrun.platforms
|
|
34
38
|
import mlrun.utils.helpers
|
|
35
39
|
from mlrun.common.helpers import parse_versioned_object_uri
|
|
36
40
|
from mlrun.runtimes.mounts import auto_mount as auto_mount_modifier
|
|
@@ -63,12 +67,19 @@ from .utils.version import Version
|
|
|
63
67
|
pd.set_option("mode.chained_assignment", None)
|
|
64
68
|
|
|
65
69
|
|
|
66
|
-
def validate_base_argument(ctx, param, value):
|
|
70
|
+
def validate_base_argument(ctx: click.Context, param: click.Parameter, value: str):
|
|
71
|
+
# click 8.2 expects the context to be passed to make_metavar
|
|
72
|
+
if semver.VersionInfo.parse(
|
|
73
|
+
importlib.metadata.version("click")
|
|
74
|
+
) < semver.VersionInfo.parse("8.2.0"):
|
|
75
|
+
metavar_func = functools.partial(param.make_metavar)
|
|
76
|
+
else:
|
|
77
|
+
metavar_func = functools.partial(param.make_metavar, ctx)
|
|
67
78
|
if value and value.startswith("-"):
|
|
68
79
|
raise click.BadParameter(
|
|
69
80
|
f"{param.human_readable_name} ({value}) cannot start with '-', ensure the command options are typed "
|
|
70
81
|
f"correctly. Preferably use '--' to separate options and arguments "
|
|
71
|
-
f"e.g. 'mlrun run --option1 --option2 -- {
|
|
82
|
+
f"e.g. 'mlrun run --option1 --option2 -- {metavar_func()} [--arg1|arg1] [--arg2|arg2]'",
|
|
72
83
|
ctx=ctx,
|
|
73
84
|
param=param,
|
|
74
85
|
)
|
mlrun/common/constants.py
CHANGED
|
@@ -90,6 +90,13 @@ class MLRunInternalLabels:
|
|
|
90
90
|
if not key.startswith("__") and isinstance(value, str)
|
|
91
91
|
]
|
|
92
92
|
|
|
93
|
+
@staticmethod
|
|
94
|
+
def default_run_labels_to_enrich():
|
|
95
|
+
return [
|
|
96
|
+
MLRunInternalLabels.owner,
|
|
97
|
+
MLRunInternalLabels.v3io_user,
|
|
98
|
+
]
|
|
99
|
+
|
|
93
100
|
|
|
94
101
|
class DeployStatusTextKind(mlrun.common.types.StrEnum):
|
|
95
102
|
logs = "logs"
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
import enum
|
|
16
16
|
import typing
|
|
17
17
|
|
|
18
|
+
from deprecated import deprecated
|
|
19
|
+
|
|
18
20
|
import mlrun.common.constants as mlrun_constants
|
|
19
21
|
import mlrun_pipelines.common.models
|
|
20
22
|
|
|
@@ -237,7 +239,12 @@ class RunStates:
|
|
|
237
239
|
}[pipeline_run_status]
|
|
238
240
|
|
|
239
241
|
|
|
240
|
-
# TODO: remove this class in 1.
|
|
242
|
+
# TODO: remove this class in 1.11.0 - use only MLRunInternalLabels
|
|
243
|
+
@deprecated(
|
|
244
|
+
version="1.9.0",
|
|
245
|
+
reason="This class is deprecated and will be removed in 1.11.0. Use MLRunInternalLabels instead.",
|
|
246
|
+
category=FutureWarning,
|
|
247
|
+
)
|
|
241
248
|
class RunLabels(enum.Enum):
|
|
242
249
|
owner = mlrun_constants.MLRunInternalLabels.owner
|
|
243
250
|
v3io_user = mlrun_constants.MLRunInternalLabels.v3io_user
|
mlrun/common/schemas/__init__.py
CHANGED
mlrun/common/schemas/serving.py
CHANGED
|
@@ -14,9 +14,26 @@
|
|
|
14
14
|
|
|
15
15
|
from pydantic.v1 import BaseModel
|
|
16
16
|
|
|
17
|
+
from mlrun.common.types import StrEnum
|
|
18
|
+
|
|
17
19
|
from .background_task import BackgroundTaskList
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
class DeployResponse(BaseModel):
|
|
21
23
|
data: dict
|
|
22
24
|
background_tasks: BackgroundTaskList
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ModelRunnerStepData(StrEnum):
|
|
28
|
+
MODELS = "models"
|
|
29
|
+
MONITORING_DATA = "monitoring_data"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MonitoringData(StrEnum):
|
|
33
|
+
INPUTS = "inputs"
|
|
34
|
+
OUTPUTS = "outputs"
|
|
35
|
+
INPUT_PATH = "input_path"
|
|
36
|
+
CREATION_STRATEGY = "creation_strategy"
|
|
37
|
+
LABELS = "labels"
|
|
38
|
+
MODEL_PATH = "model_path"
|
|
39
|
+
MODEL_ENDPOINT_UID = "model_endpoint_uid"
|
|
@@ -16,7 +16,6 @@ import ast
|
|
|
16
16
|
import base64
|
|
17
17
|
import json
|
|
18
18
|
import typing
|
|
19
|
-
import warnings
|
|
20
19
|
from urllib.parse import ParseResult, urlparse
|
|
21
20
|
|
|
22
21
|
import pydantic.v1
|
|
@@ -142,7 +141,6 @@ class ConfigProfile(DatastoreProfile):
|
|
|
142
141
|
class DatastoreProfileKafkaTarget(DatastoreProfile):
|
|
143
142
|
type: str = pydantic.v1.Field("kafka_target")
|
|
144
143
|
_private_attributes = "kwargs_private"
|
|
145
|
-
bootstrap_servers: typing.Optional[str] = None
|
|
146
144
|
brokers: typing.Optional[str] = None
|
|
147
145
|
topic: str
|
|
148
146
|
kwargs_public: typing.Optional[dict]
|
|
@@ -151,31 +149,16 @@ class DatastoreProfileKafkaTarget(DatastoreProfile):
|
|
|
151
149
|
def __init__(self, **kwargs):
|
|
152
150
|
super().__init__(**kwargs)
|
|
153
151
|
|
|
154
|
-
if not self.brokers
|
|
152
|
+
if not self.brokers:
|
|
155
153
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
156
154
|
"DatastoreProfileKafkaTarget requires the 'brokers' field to be set"
|
|
157
155
|
)
|
|
158
156
|
|
|
159
|
-
if self.bootstrap_servers:
|
|
160
|
-
if self.brokers:
|
|
161
|
-
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
162
|
-
"DatastoreProfileKafkaTarget cannot be created with both 'brokers' and 'bootstrap_servers'"
|
|
163
|
-
)
|
|
164
|
-
else:
|
|
165
|
-
self.brokers = self.bootstrap_servers
|
|
166
|
-
self.bootstrap_servers = None
|
|
167
|
-
warnings.warn(
|
|
168
|
-
"'bootstrap_servers' parameter is deprecated in 1.7.0 and will be removed in 1.9.0, "
|
|
169
|
-
"use 'brokers' instead.",
|
|
170
|
-
# TODO: Remove this in 1.9.0
|
|
171
|
-
FutureWarning,
|
|
172
|
-
)
|
|
173
|
-
|
|
174
157
|
def get_topic(self) -> typing.Optional[str]:
|
|
175
158
|
return self.topic
|
|
176
159
|
|
|
177
160
|
def attributes(self):
|
|
178
|
-
attributes = {"brokers": self.brokers
|
|
161
|
+
attributes = {"brokers": self.brokers}
|
|
179
162
|
if self.kwargs_public:
|
|
180
163
|
attributes = merge(attributes, self.kwargs_public)
|
|
181
164
|
if self.kwargs_private:
|
|
@@ -248,18 +231,7 @@ class DatastoreProfileS3(DatastoreProfile):
|
|
|
248
231
|
assume_role_arn: typing.Optional[str] = None
|
|
249
232
|
access_key_id: typing.Optional[str] = None
|
|
250
233
|
secret_key: typing.Optional[str] = None
|
|
251
|
-
bucket:
|
|
252
|
-
|
|
253
|
-
@pydantic.v1.validator("bucket")
|
|
254
|
-
@classmethod
|
|
255
|
-
def check_bucket(cls, v):
|
|
256
|
-
if not v:
|
|
257
|
-
warnings.warn(
|
|
258
|
-
"The 'bucket' attribute will be mandatory starting from version 1.9",
|
|
259
|
-
FutureWarning,
|
|
260
|
-
stacklevel=2,
|
|
261
|
-
)
|
|
262
|
-
return v
|
|
234
|
+
bucket: str
|
|
263
235
|
|
|
264
236
|
def secrets(self) -> dict:
|
|
265
237
|
res = {}
|
|
@@ -353,18 +325,7 @@ class DatastoreProfileGCS(DatastoreProfile):
|
|
|
353
325
|
_private_attributes = ("gcp_credentials",)
|
|
354
326
|
credentials_path: typing.Optional[str] = None # path to file.
|
|
355
327
|
gcp_credentials: typing.Optional[typing.Union[str, dict]] = None
|
|
356
|
-
bucket:
|
|
357
|
-
|
|
358
|
-
@pydantic.v1.validator("bucket")
|
|
359
|
-
@classmethod
|
|
360
|
-
def check_bucket(cls, v):
|
|
361
|
-
if not v:
|
|
362
|
-
warnings.warn(
|
|
363
|
-
"The 'bucket' attribute will be mandatory starting from version 1.9",
|
|
364
|
-
FutureWarning,
|
|
365
|
-
stacklevel=2,
|
|
366
|
-
)
|
|
367
|
-
return v
|
|
328
|
+
bucket: str
|
|
368
329
|
|
|
369
330
|
@pydantic.v1.validator("gcp_credentials", pre=True, always=True)
|
|
370
331
|
@classmethod
|
|
@@ -410,18 +371,7 @@ class DatastoreProfileAzureBlob(DatastoreProfile):
|
|
|
410
371
|
client_secret: typing.Optional[str] = None
|
|
411
372
|
sas_token: typing.Optional[str] = None
|
|
412
373
|
credential: typing.Optional[str] = None
|
|
413
|
-
container:
|
|
414
|
-
|
|
415
|
-
@pydantic.v1.validator("container")
|
|
416
|
-
@classmethod
|
|
417
|
-
def check_container(cls, v):
|
|
418
|
-
if not v:
|
|
419
|
-
warnings.warn(
|
|
420
|
-
"The 'container' attribute will be mandatory starting from version 1.9",
|
|
421
|
-
FutureWarning,
|
|
422
|
-
stacklevel=2,
|
|
423
|
-
)
|
|
424
|
-
return v
|
|
374
|
+
container: str
|
|
425
375
|
|
|
426
376
|
def url(self, subpath) -> str:
|
|
427
377
|
if subpath.startswith("/"):
|
mlrun/datastore/sources.py
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
14
15
|
import json
|
|
15
16
|
import operator
|
|
16
17
|
import os
|
|
@@ -18,7 +19,7 @@ import warnings
|
|
|
18
19
|
from base64 import b64encode
|
|
19
20
|
from copy import copy
|
|
20
21
|
from datetime import datetime
|
|
21
|
-
from typing import Any, Optional, Union
|
|
22
|
+
from typing import Any, Literal, Optional, Union
|
|
22
23
|
|
|
23
24
|
import pandas as pd
|
|
24
25
|
import semver
|
|
@@ -1063,16 +1064,17 @@ class KafkaSource(OnlineSource):
|
|
|
1063
1064
|
|
|
1064
1065
|
def __init__(
|
|
1065
1066
|
self,
|
|
1066
|
-
brokers=None,
|
|
1067
|
-
topics=None,
|
|
1068
|
-
group="serving",
|
|
1069
|
-
initial_offset="earliest",
|
|
1070
|
-
partitions=None,
|
|
1071
|
-
sasl_user=None,
|
|
1072
|
-
sasl_pass=None,
|
|
1073
|
-
|
|
1067
|
+
brokers: Optional[list[str]] = None,
|
|
1068
|
+
topics: Optional[list[str]] = None,
|
|
1069
|
+
group: str = "serving",
|
|
1070
|
+
initial_offset: Literal["earliest", "latest"] = "earliest",
|
|
1071
|
+
partitions: Optional[list[int]] = None,
|
|
1072
|
+
sasl_user: Optional[str] = None,
|
|
1073
|
+
sasl_pass: Optional[str] = None,
|
|
1074
|
+
tls_enable: Optional[bool] = None,
|
|
1075
|
+
attributes: Optional[dict] = None,
|
|
1074
1076
|
**kwargs,
|
|
1075
|
-
):
|
|
1077
|
+
) -> None:
|
|
1076
1078
|
"""Sets kafka source for the flow
|
|
1077
1079
|
|
|
1078
1080
|
:param brokers: list of broker IP addresses
|
|
@@ -1082,6 +1084,7 @@ class KafkaSource(OnlineSource):
|
|
|
1082
1084
|
:param partitions: Optional, A list of partitions numbers for which the function receives events.
|
|
1083
1085
|
:param sasl_user: Optional, user name to use for sasl authentications
|
|
1084
1086
|
:param sasl_pass: Optional, password to use for sasl authentications
|
|
1087
|
+
:param tls_enable: Optional, if set - whether to enable TLS or not.
|
|
1085
1088
|
:param attributes: Optional, extra attributes to be passed to kafka trigger
|
|
1086
1089
|
"""
|
|
1087
1090
|
if isinstance(topics, str):
|
|
@@ -1095,10 +1098,15 @@ class KafkaSource(OnlineSource):
|
|
|
1095
1098
|
attributes["initial_offset"] = initial_offset
|
|
1096
1099
|
if partitions is not None:
|
|
1097
1100
|
attributes["partitions"] = partitions
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
+
|
|
1102
|
+
kafka_params = mlrun.datastore.utils.KafkaParameters(attributes)
|
|
1103
|
+
|
|
1104
|
+
if sasl := kafka_params.sasl(usr=sasl_user, pwd=sasl_pass):
|
|
1101
1105
|
attributes["sasl"] = sasl
|
|
1106
|
+
|
|
1107
|
+
if tls := kafka_params.tls(tls_enable=tls_enable):
|
|
1108
|
+
attributes["tls"] = tls
|
|
1109
|
+
|
|
1102
1110
|
super().__init__(attributes=attributes, **kwargs)
|
|
1103
1111
|
|
|
1104
1112
|
def to_dataframe(
|
mlrun/datastore/utils.py
CHANGED
|
@@ -246,6 +246,9 @@ class KafkaParameters:
|
|
|
246
246
|
"partitions": "",
|
|
247
247
|
"sasl": "",
|
|
248
248
|
"worker_allocation_mode": "",
|
|
249
|
+
"tls_enable": "", # for Nuclio with Confluent Kafka (Sarama client)
|
|
250
|
+
"tls": "",
|
|
251
|
+
"new_topic": "",
|
|
249
252
|
}
|
|
250
253
|
self._reference_dicts = (
|
|
251
254
|
self._custom_attributes,
|
|
@@ -270,7 +273,9 @@ class KafkaParameters:
|
|
|
270
273
|
}
|
|
271
274
|
if sasl := self._kwargs.get("sasl"):
|
|
272
275
|
res |= {
|
|
273
|
-
"security_protocol":
|
|
276
|
+
"security_protocol": self._kwargs.get(
|
|
277
|
+
"security_protocol", "SASL_PLAINTEXT"
|
|
278
|
+
),
|
|
274
279
|
"sasl_mechanism": sasl["mechanism"],
|
|
275
280
|
"sasl_plain_username": sasl["user"],
|
|
276
281
|
"sasl_plain_password": sasl["password"],
|
|
@@ -288,15 +293,25 @@ class KafkaParameters:
|
|
|
288
293
|
|
|
289
294
|
def sasl(
|
|
290
295
|
self, *, usr: typing.Optional[str] = None, pwd: typing.Optional[str] = None
|
|
291
|
-
) -> dict:
|
|
292
|
-
usr = usr or self._kwargs.get("sasl_plain_username", None)
|
|
293
|
-
pwd = pwd or self._kwargs.get("sasl_plain_password", None)
|
|
296
|
+
) -> dict[str, typing.Union[str, bool]]:
|
|
294
297
|
res = self._kwargs.get("sasl", {})
|
|
298
|
+
usr = usr or self._kwargs.get("sasl_plain_username")
|
|
299
|
+
pwd = pwd or self._kwargs.get("sasl_plain_password")
|
|
295
300
|
if usr and pwd:
|
|
296
301
|
res["enable"] = True
|
|
297
302
|
res["user"] = usr
|
|
298
303
|
res["password"] = pwd
|
|
299
304
|
res["mechanism"] = self._kwargs.get("sasl_mechanism", "PLAIN")
|
|
305
|
+
res["handshake"] = self._kwargs.get("sasl_handshake", True)
|
|
306
|
+
return res
|
|
307
|
+
|
|
308
|
+
def tls(self, *, tls_enable: typing.Optional[bool] = None) -> dict[str, bool]:
|
|
309
|
+
res = self._kwargs.get("tls", {})
|
|
310
|
+
tls_enable = (
|
|
311
|
+
tls_enable if tls_enable is not None else self._kwargs.get("tls_enable")
|
|
312
|
+
)
|
|
313
|
+
if tls_enable:
|
|
314
|
+
res["enable"] = tls_enable
|
|
300
315
|
return res
|
|
301
316
|
|
|
302
317
|
def valid_entries_only(self, input_dict: dict) -> dict:
|
mlrun/db/base.py
CHANGED
|
@@ -734,7 +734,7 @@ class RunDBInterface(ABC):
|
|
|
734
734
|
labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
|
|
735
735
|
start: Optional[datetime.datetime] = None,
|
|
736
736
|
end: Optional[datetime.datetime] = None,
|
|
737
|
-
tsdb_metrics: bool =
|
|
737
|
+
tsdb_metrics: bool = False,
|
|
738
738
|
metric_list: Optional[list[str]] = None,
|
|
739
739
|
top_level: bool = False,
|
|
740
740
|
uids: Optional[list[str]] = None,
|
mlrun/db/httpdb.py
CHANGED
|
@@ -21,7 +21,7 @@ import typing
|
|
|
21
21
|
import warnings
|
|
22
22
|
from copy import deepcopy
|
|
23
23
|
from datetime import datetime, timedelta
|
|
24
|
-
from os import path, remove
|
|
24
|
+
from os import environ, path, remove
|
|
25
25
|
from typing import Literal, Optional, Union
|
|
26
26
|
from urllib.parse import urlparse
|
|
27
27
|
|
|
@@ -129,7 +129,9 @@ class HTTPRunDB(RunDBInterface):
|
|
|
129
129
|
self._wait_for_background_task_terminal_state_retry_interval = 3
|
|
130
130
|
self._wait_for_project_deletion_interval = 3
|
|
131
131
|
self.client_version = version.Version().get()["version"]
|
|
132
|
-
self.python_version =
|
|
132
|
+
self.python_version = environ.get("MLRUN_PYTHON_VERSION") or str(
|
|
133
|
+
version.Version().get_python_version()
|
|
134
|
+
)
|
|
133
135
|
|
|
134
136
|
self._enrich_and_validate(url)
|
|
135
137
|
|
|
@@ -1276,8 +1278,8 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1276
1278
|
:param producer_uri: Return artifacts produced by the requested producer URI. Producer URI usually
|
|
1277
1279
|
points to a run and is used to filter artifacts by the run that produced them when the artifact producer id
|
|
1278
1280
|
is a workflow id (artifact was created as part of a workflow).
|
|
1279
|
-
:param format_:
|
|
1280
|
-
:param limit:
|
|
1281
|
+
:param format_: The format in which to return the artifacts. Default is 'full'.
|
|
1282
|
+
:param limit: Deprecated - Maximum number of artifacts to return (will be removed in 1.11.0).
|
|
1281
1283
|
:param partition_by: Field to group results by. When `partition_by` is specified, the `partition_sort_by`
|
|
1282
1284
|
parameter must be provided as well.
|
|
1283
1285
|
:param rows_per_partition: How many top rows (per sorting defined by `partition_sort_by` and `partition_order`)
|
|
@@ -2221,18 +2223,20 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2221
2223
|
elif pipe_file.endswith(".zip"):
|
|
2222
2224
|
headers = {"content-type": "application/zip"}
|
|
2223
2225
|
else:
|
|
2224
|
-
raise ValueError("pipeline file must be .yaml or .zip")
|
|
2226
|
+
raise ValueError("'pipeline' file must be .yaml or .zip")
|
|
2225
2227
|
if arguments:
|
|
2226
2228
|
if not isinstance(arguments, dict):
|
|
2227
|
-
raise ValueError("arguments must be dict type")
|
|
2229
|
+
raise ValueError("'arguments' must be dict type")
|
|
2228
2230
|
headers[mlrun.common.schemas.HeaderNames.pipeline_arguments] = str(
|
|
2229
2231
|
arguments
|
|
2230
2232
|
)
|
|
2231
2233
|
|
|
2232
2234
|
if not path.isfile(pipe_file):
|
|
2233
|
-
raise OSError(f"
|
|
2235
|
+
raise OSError(f"File {pipe_file} doesnt exist")
|
|
2234
2236
|
with open(pipe_file, "rb") as fp:
|
|
2235
2237
|
data = fp.read()
|
|
2238
|
+
if not data:
|
|
2239
|
+
raise ValueError("The compiled pipe file is empty")
|
|
2236
2240
|
if not isinstance(pipeline, str):
|
|
2237
2241
|
remove(pipe_file)
|
|
2238
2242
|
|
|
@@ -3767,7 +3771,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3767
3771
|
labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
|
|
3768
3772
|
start: Optional[datetime] = None,
|
|
3769
3773
|
end: Optional[datetime] = None,
|
|
3770
|
-
tsdb_metrics: bool =
|
|
3774
|
+
tsdb_metrics: bool = False,
|
|
3771
3775
|
metric_list: Optional[list[str]] = None,
|
|
3772
3776
|
top_level: bool = False,
|
|
3773
3777
|
uids: Optional[list[str]] = None,
|
|
@@ -3889,8 +3893,8 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3889
3893
|
attributes_keys = list(attributes.keys())
|
|
3890
3894
|
attributes["name"] = name
|
|
3891
3895
|
attributes["project"] = project
|
|
3892
|
-
attributes["
|
|
3893
|
-
attributes["
|
|
3896
|
+
attributes["function_name"] = function_name or None
|
|
3897
|
+
attributes["function_tag"] = function_tag or None
|
|
3894
3898
|
attributes["uid"] = endpoint_id or None
|
|
3895
3899
|
model_endpoint = mlrun.common.schemas.ModelEndpoint.from_flat_dict(attributes)
|
|
3896
3900
|
path = f"projects/{project}/model-endpoints"
|
|
@@ -3981,6 +3985,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3981
3985
|
"deploy_histogram_data_drift_app": deploy_histogram_data_drift_app,
|
|
3982
3986
|
"fetch_credentials_from_sys_config": fetch_credentials_from_sys_config,
|
|
3983
3987
|
},
|
|
3988
|
+
timeout=300, # 5 minutes
|
|
3984
3989
|
)
|
|
3985
3990
|
|
|
3986
3991
|
def disable_model_monitoring(
|
|
@@ -5099,6 +5104,13 @@ class HTTPRunDB(RunDBInterface):
|
|
|
5099
5104
|
project = project or config.default_project
|
|
5100
5105
|
labels = self._parse_labels(labels)
|
|
5101
5106
|
|
|
5107
|
+
if limit:
|
|
5108
|
+
# TODO: Remove this in 1.11.0
|
|
5109
|
+
warnings.warn(
|
|
5110
|
+
"'limit' is deprecated and will be removed in 1.11.0. Use 'page' and 'page_size' instead.",
|
|
5111
|
+
FutureWarning,
|
|
5112
|
+
)
|
|
5113
|
+
|
|
5102
5114
|
params = {
|
|
5103
5115
|
"name": name,
|
|
5104
5116
|
"tag": tag,
|
mlrun/db/nopdb.py
CHANGED
|
@@ -630,7 +630,7 @@ class NopDB(RunDBInterface):
|
|
|
630
630
|
labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
|
|
631
631
|
start: Optional[datetime.datetime] = None,
|
|
632
632
|
end: Optional[datetime.datetime] = None,
|
|
633
|
-
tsdb_metrics: bool =
|
|
633
|
+
tsdb_metrics: bool = False,
|
|
634
634
|
metric_list: Optional[list[str]] = None,
|
|
635
635
|
top_level: bool = False,
|
|
636
636
|
uids: Optional[list[str]] = None,
|
mlrun/errors.py
CHANGED
|
@@ -230,6 +230,13 @@ class MLRunTSDBConnectionFailureError(MLRunHTTPStatusError, ValueError):
|
|
|
230
230
|
error_status_code = HTTPStatus.BAD_REQUEST.value
|
|
231
231
|
|
|
232
232
|
|
|
233
|
+
class MLRunMissingProjectError(MLRunBadRequestError):
|
|
234
|
+
default_message = "Project must be provided"
|
|
235
|
+
|
|
236
|
+
def __init__(self, message=None):
|
|
237
|
+
super().__init__(message or self.default_message)
|
|
238
|
+
|
|
239
|
+
|
|
233
240
|
class MLRunRetryExhaustedError(Exception):
|
|
234
241
|
pass
|
|
235
242
|
|
mlrun/execution.py
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import logging
|
|
16
16
|
import os
|
|
17
17
|
import uuid
|
|
18
|
+
import warnings
|
|
18
19
|
from copy import deepcopy
|
|
19
20
|
from typing import Optional, Union, cast
|
|
20
21
|
|
|
@@ -991,6 +992,14 @@ class MLClientCtx:
|
|
|
991
992
|
self._update_run()
|
|
992
993
|
return item
|
|
993
994
|
|
|
995
|
+
def get_cached_artifact(self, key):
|
|
996
|
+
"""Return a logged artifact from cache (for potential updates)"""
|
|
997
|
+
warnings.warn(
|
|
998
|
+
"get_cached_artifact is deprecated in 1.8.0 and will be removed in 1.11.0. Use get_artifact instead.",
|
|
999
|
+
FutureWarning,
|
|
1000
|
+
)
|
|
1001
|
+
return self.get_artifact(key)
|
|
1002
|
+
|
|
994
1003
|
def get_artifact(
|
|
995
1004
|
self, key, tag=None, iter=None, tree=None, uid=None
|
|
996
1005
|
) -> Optional[Artifact]:
|
mlrun/launcher/client.py
CHANGED
|
@@ -72,7 +72,7 @@ class ClientBaseLauncher(launcher.BaseLauncher, abc.ABC):
|
|
|
72
72
|
):
|
|
73
73
|
run.metadata.labels[mlrun_constants.MLRunInternalLabels.kind] = runtime.kind
|
|
74
74
|
mlrun.runtimes.utils.enrich_run_labels(
|
|
75
|
-
run.metadata.labels, [
|
|
75
|
+
run.metadata.labels, [mlrun_constants.MLRunInternalLabels.owner]
|
|
76
76
|
)
|
|
77
77
|
if run.spec.output_path:
|
|
78
78
|
run.spec.output_path = run.spec.output_path.replace(
|