mlrun 1.6.4rc7__py3-none-any.whl → 1.7.0__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.

Files changed (305) hide show
  1. mlrun/__init__.py +11 -1
  2. mlrun/__main__.py +40 -122
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +248 -0
  5. mlrun/api/schemas/__init__.py +5 -4
  6. mlrun/artifacts/__init__.py +8 -3
  7. mlrun/artifacts/base.py +47 -257
  8. mlrun/artifacts/dataset.py +11 -192
  9. mlrun/artifacts/manager.py +79 -47
  10. mlrun/artifacts/model.py +31 -159
  11. mlrun/artifacts/plots.py +23 -380
  12. mlrun/common/constants.py +74 -1
  13. mlrun/common/db/sql_session.py +5 -5
  14. mlrun/common/formatters/__init__.py +21 -0
  15. mlrun/common/formatters/artifact.py +45 -0
  16. mlrun/common/formatters/base.py +113 -0
  17. mlrun/common/formatters/feature_set.py +33 -0
  18. mlrun/common/formatters/function.py +46 -0
  19. mlrun/common/formatters/pipeline.py +53 -0
  20. mlrun/common/formatters/project.py +51 -0
  21. mlrun/common/formatters/run.py +29 -0
  22. mlrun/common/helpers.py +12 -3
  23. mlrun/common/model_monitoring/helpers.py +9 -5
  24. mlrun/{runtimes → common/runtimes}/constants.py +37 -9
  25. mlrun/common/schemas/__init__.py +31 -5
  26. mlrun/common/schemas/alert.py +202 -0
  27. mlrun/common/schemas/api_gateway.py +196 -0
  28. mlrun/common/schemas/artifact.py +25 -4
  29. mlrun/common/schemas/auth.py +16 -5
  30. mlrun/common/schemas/background_task.py +1 -1
  31. mlrun/common/schemas/client_spec.py +4 -2
  32. mlrun/common/schemas/common.py +7 -4
  33. mlrun/common/schemas/constants.py +3 -0
  34. mlrun/common/schemas/feature_store.py +74 -44
  35. mlrun/common/schemas/frontend_spec.py +15 -7
  36. mlrun/common/schemas/function.py +12 -1
  37. mlrun/common/schemas/hub.py +11 -18
  38. mlrun/common/schemas/memory_reports.py +2 -2
  39. mlrun/common/schemas/model_monitoring/__init__.py +20 -4
  40. mlrun/common/schemas/model_monitoring/constants.py +123 -42
  41. mlrun/common/schemas/model_monitoring/grafana.py +13 -9
  42. mlrun/common/schemas/model_monitoring/model_endpoints.py +101 -54
  43. mlrun/common/schemas/notification.py +71 -14
  44. mlrun/common/schemas/object.py +2 -2
  45. mlrun/{model_monitoring/controller_handler.py → common/schemas/pagination.py} +9 -12
  46. mlrun/common/schemas/pipeline.py +8 -1
  47. mlrun/common/schemas/project.py +69 -18
  48. mlrun/common/schemas/runs.py +7 -1
  49. mlrun/common/schemas/runtime_resource.py +8 -12
  50. mlrun/common/schemas/schedule.py +4 -4
  51. mlrun/common/schemas/tag.py +1 -2
  52. mlrun/common/schemas/workflow.py +12 -4
  53. mlrun/common/types.py +14 -1
  54. mlrun/config.py +154 -69
  55. mlrun/data_types/data_types.py +6 -1
  56. mlrun/data_types/spark.py +2 -2
  57. mlrun/data_types/to_pandas.py +67 -37
  58. mlrun/datastore/__init__.py +6 -8
  59. mlrun/datastore/alibaba_oss.py +131 -0
  60. mlrun/datastore/azure_blob.py +143 -42
  61. mlrun/datastore/base.py +102 -58
  62. mlrun/datastore/datastore.py +34 -13
  63. mlrun/datastore/datastore_profile.py +146 -20
  64. mlrun/datastore/dbfs_store.py +3 -7
  65. mlrun/datastore/filestore.py +1 -4
  66. mlrun/datastore/google_cloud_storage.py +97 -33
  67. mlrun/datastore/hdfs.py +56 -0
  68. mlrun/datastore/inmem.py +6 -3
  69. mlrun/datastore/redis.py +7 -2
  70. mlrun/datastore/s3.py +34 -12
  71. mlrun/datastore/snowflake_utils.py +45 -0
  72. mlrun/datastore/sources.py +303 -111
  73. mlrun/datastore/spark_utils.py +31 -2
  74. mlrun/datastore/store_resources.py +9 -7
  75. mlrun/datastore/storeytargets.py +151 -0
  76. mlrun/datastore/targets.py +453 -176
  77. mlrun/datastore/utils.py +72 -58
  78. mlrun/datastore/v3io.py +6 -1
  79. mlrun/db/base.py +274 -41
  80. mlrun/db/factory.py +1 -1
  81. mlrun/db/httpdb.py +893 -225
  82. mlrun/db/nopdb.py +291 -33
  83. mlrun/errors.py +36 -6
  84. mlrun/execution.py +115 -42
  85. mlrun/feature_store/__init__.py +0 -2
  86. mlrun/feature_store/api.py +65 -73
  87. mlrun/feature_store/common.py +7 -12
  88. mlrun/feature_store/feature_set.py +76 -55
  89. mlrun/feature_store/feature_vector.py +39 -31
  90. mlrun/feature_store/ingestion.py +7 -6
  91. mlrun/feature_store/retrieval/base.py +16 -11
  92. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  93. mlrun/feature_store/retrieval/job.py +13 -4
  94. mlrun/feature_store/retrieval/local_merger.py +2 -0
  95. mlrun/feature_store/retrieval/spark_merger.py +24 -32
  96. mlrun/feature_store/steps.py +45 -34
  97. mlrun/features.py +11 -21
  98. mlrun/frameworks/_common/artifacts_library.py +9 -9
  99. mlrun/frameworks/_common/mlrun_interface.py +5 -5
  100. mlrun/frameworks/_common/model_handler.py +48 -48
  101. mlrun/frameworks/_common/plan.py +5 -6
  102. mlrun/frameworks/_common/producer.py +3 -4
  103. mlrun/frameworks/_common/utils.py +5 -5
  104. mlrun/frameworks/_dl_common/loggers/logger.py +6 -7
  105. mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +9 -9
  106. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +23 -47
  107. mlrun/frameworks/_ml_common/artifacts_library.py +1 -2
  108. mlrun/frameworks/_ml_common/loggers/logger.py +3 -4
  109. mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +4 -5
  110. mlrun/frameworks/_ml_common/model_handler.py +24 -24
  111. mlrun/frameworks/_ml_common/pkl_model_server.py +2 -2
  112. mlrun/frameworks/_ml_common/plan.py +2 -2
  113. mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +2 -3
  114. mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +2 -3
  115. mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
  116. mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +3 -3
  117. mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
  118. mlrun/frameworks/_ml_common/utils.py +4 -4
  119. mlrun/frameworks/auto_mlrun/auto_mlrun.py +9 -9
  120. mlrun/frameworks/huggingface/model_server.py +4 -4
  121. mlrun/frameworks/lgbm/__init__.py +33 -33
  122. mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
  123. mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -5
  124. mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -5
  125. mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -3
  126. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +6 -6
  127. mlrun/frameworks/lgbm/model_handler.py +10 -10
  128. mlrun/frameworks/lgbm/model_server.py +6 -6
  129. mlrun/frameworks/lgbm/utils.py +5 -5
  130. mlrun/frameworks/onnx/dataset.py +8 -8
  131. mlrun/frameworks/onnx/mlrun_interface.py +3 -3
  132. mlrun/frameworks/onnx/model_handler.py +6 -6
  133. mlrun/frameworks/onnx/model_server.py +7 -7
  134. mlrun/frameworks/parallel_coordinates.py +6 -6
  135. mlrun/frameworks/pytorch/__init__.py +18 -18
  136. mlrun/frameworks/pytorch/callbacks/callback.py +4 -5
  137. mlrun/frameworks/pytorch/callbacks/logging_callback.py +17 -17
  138. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +11 -11
  139. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +23 -29
  140. mlrun/frameworks/pytorch/callbacks_handler.py +38 -38
  141. mlrun/frameworks/pytorch/mlrun_interface.py +20 -20
  142. mlrun/frameworks/pytorch/model_handler.py +17 -17
  143. mlrun/frameworks/pytorch/model_server.py +7 -7
  144. mlrun/frameworks/sklearn/__init__.py +13 -13
  145. mlrun/frameworks/sklearn/estimator.py +4 -4
  146. mlrun/frameworks/sklearn/metrics_library.py +14 -14
  147. mlrun/frameworks/sklearn/mlrun_interface.py +16 -9
  148. mlrun/frameworks/sklearn/model_handler.py +2 -2
  149. mlrun/frameworks/tf_keras/__init__.py +10 -7
  150. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +15 -15
  151. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +11 -11
  152. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +19 -23
  153. mlrun/frameworks/tf_keras/mlrun_interface.py +9 -11
  154. mlrun/frameworks/tf_keras/model_handler.py +14 -14
  155. mlrun/frameworks/tf_keras/model_server.py +6 -6
  156. mlrun/frameworks/xgboost/__init__.py +13 -13
  157. mlrun/frameworks/xgboost/model_handler.py +6 -6
  158. mlrun/k8s_utils.py +61 -17
  159. mlrun/launcher/__init__.py +1 -1
  160. mlrun/launcher/base.py +16 -15
  161. mlrun/launcher/client.py +13 -11
  162. mlrun/launcher/factory.py +1 -1
  163. mlrun/launcher/local.py +23 -13
  164. mlrun/launcher/remote.py +17 -10
  165. mlrun/lists.py +7 -6
  166. mlrun/model.py +478 -103
  167. mlrun/model_monitoring/__init__.py +1 -1
  168. mlrun/model_monitoring/api.py +163 -371
  169. mlrun/{runtimes/mpijob/v1alpha1.py → model_monitoring/applications/__init__.py} +9 -15
  170. mlrun/model_monitoring/applications/_application_steps.py +188 -0
  171. mlrun/model_monitoring/applications/base.py +108 -0
  172. mlrun/model_monitoring/applications/context.py +341 -0
  173. mlrun/model_monitoring/{evidently_application.py → applications/evidently_base.py} +27 -22
  174. mlrun/model_monitoring/applications/histogram_data_drift.py +354 -0
  175. mlrun/model_monitoring/applications/results.py +99 -0
  176. mlrun/model_monitoring/controller.py +131 -278
  177. mlrun/model_monitoring/db/__init__.py +18 -0
  178. mlrun/model_monitoring/db/stores/__init__.py +136 -0
  179. mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
  180. mlrun/model_monitoring/db/stores/base/store.py +213 -0
  181. mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
  182. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
  183. mlrun/model_monitoring/db/stores/sqldb/models/base.py +190 -0
  184. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +103 -0
  185. mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
  186. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +659 -0
  187. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
  188. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +726 -0
  189. mlrun/model_monitoring/db/tsdb/__init__.py +105 -0
  190. mlrun/model_monitoring/db/tsdb/base.py +448 -0
  191. mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
  192. mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
  193. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +279 -0
  194. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +42 -0
  195. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +507 -0
  196. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  197. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +158 -0
  198. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +849 -0
  199. mlrun/model_monitoring/features_drift_table.py +134 -106
  200. mlrun/model_monitoring/helpers.py +199 -55
  201. mlrun/model_monitoring/metrics/__init__.py +13 -0
  202. mlrun/model_monitoring/metrics/histogram_distance.py +127 -0
  203. mlrun/model_monitoring/model_endpoint.py +3 -2
  204. mlrun/model_monitoring/stream_processing.py +131 -398
  205. mlrun/model_monitoring/tracking_policy.py +9 -2
  206. mlrun/model_monitoring/writer.py +161 -125
  207. mlrun/package/__init__.py +6 -6
  208. mlrun/package/context_handler.py +5 -5
  209. mlrun/package/packager.py +7 -7
  210. mlrun/package/packagers/default_packager.py +8 -8
  211. mlrun/package/packagers/numpy_packagers.py +15 -15
  212. mlrun/package/packagers/pandas_packagers.py +5 -5
  213. mlrun/package/packagers/python_standard_library_packagers.py +10 -10
  214. mlrun/package/packagers_manager.py +19 -23
  215. mlrun/package/utils/_formatter.py +6 -6
  216. mlrun/package/utils/_pickler.py +2 -2
  217. mlrun/package/utils/_supported_format.py +4 -4
  218. mlrun/package/utils/log_hint_utils.py +2 -2
  219. mlrun/package/utils/type_hint_utils.py +4 -9
  220. mlrun/platforms/__init__.py +11 -10
  221. mlrun/platforms/iguazio.py +24 -203
  222. mlrun/projects/operations.py +52 -25
  223. mlrun/projects/pipelines.py +191 -197
  224. mlrun/projects/project.py +1227 -400
  225. mlrun/render.py +16 -19
  226. mlrun/run.py +209 -184
  227. mlrun/runtimes/__init__.py +83 -15
  228. mlrun/runtimes/base.py +51 -35
  229. mlrun/runtimes/daskjob.py +17 -10
  230. mlrun/runtimes/databricks_job/databricks_cancel_task.py +1 -1
  231. mlrun/runtimes/databricks_job/databricks_runtime.py +8 -7
  232. mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
  233. mlrun/runtimes/funcdoc.py +1 -29
  234. mlrun/runtimes/function_reference.py +1 -1
  235. mlrun/runtimes/kubejob.py +34 -128
  236. mlrun/runtimes/local.py +40 -11
  237. mlrun/runtimes/mpijob/__init__.py +0 -20
  238. mlrun/runtimes/mpijob/abstract.py +9 -10
  239. mlrun/runtimes/mpijob/v1.py +1 -1
  240. mlrun/{model_monitoring/stores/models/sqlite.py → runtimes/nuclio/__init__.py} +7 -9
  241. mlrun/runtimes/nuclio/api_gateway.py +769 -0
  242. mlrun/runtimes/nuclio/application/__init__.py +15 -0
  243. mlrun/runtimes/nuclio/application/application.py +758 -0
  244. mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
  245. mlrun/runtimes/{function.py → nuclio/function.py} +200 -83
  246. mlrun/runtimes/{nuclio.py → nuclio/nuclio.py} +6 -6
  247. mlrun/runtimes/{serving.py → nuclio/serving.py} +65 -68
  248. mlrun/runtimes/pod.py +281 -101
  249. mlrun/runtimes/remotesparkjob.py +12 -9
  250. mlrun/runtimes/sparkjob/spark3job.py +67 -51
  251. mlrun/runtimes/utils.py +41 -75
  252. mlrun/secrets.py +9 -5
  253. mlrun/serving/__init__.py +8 -1
  254. mlrun/serving/remote.py +2 -7
  255. mlrun/serving/routers.py +85 -69
  256. mlrun/serving/server.py +69 -44
  257. mlrun/serving/states.py +209 -36
  258. mlrun/serving/utils.py +22 -14
  259. mlrun/serving/v1_serving.py +6 -7
  260. mlrun/serving/v2_serving.py +129 -54
  261. mlrun/track/tracker.py +2 -1
  262. mlrun/track/tracker_manager.py +3 -3
  263. mlrun/track/trackers/mlflow_tracker.py +6 -2
  264. mlrun/utils/async_http.py +6 -8
  265. mlrun/utils/azure_vault.py +1 -1
  266. mlrun/utils/clones.py +1 -2
  267. mlrun/utils/condition_evaluator.py +3 -3
  268. mlrun/utils/db.py +21 -3
  269. mlrun/utils/helpers.py +405 -225
  270. mlrun/utils/http.py +3 -6
  271. mlrun/utils/logger.py +112 -16
  272. mlrun/utils/notifications/notification/__init__.py +17 -13
  273. mlrun/utils/notifications/notification/base.py +50 -2
  274. mlrun/utils/notifications/notification/console.py +2 -0
  275. mlrun/utils/notifications/notification/git.py +24 -1
  276. mlrun/utils/notifications/notification/ipython.py +3 -1
  277. mlrun/utils/notifications/notification/slack.py +96 -21
  278. mlrun/utils/notifications/notification/webhook.py +59 -2
  279. mlrun/utils/notifications/notification_pusher.py +149 -30
  280. mlrun/utils/regex.py +9 -0
  281. mlrun/utils/retryer.py +208 -0
  282. mlrun/utils/singleton.py +1 -1
  283. mlrun/utils/v3io_clients.py +4 -6
  284. mlrun/utils/version/version.json +2 -2
  285. mlrun/utils/version/version.py +2 -6
  286. mlrun-1.7.0.dist-info/METADATA +378 -0
  287. mlrun-1.7.0.dist-info/RECORD +351 -0
  288. {mlrun-1.6.4rc7.dist-info → mlrun-1.7.0.dist-info}/WHEEL +1 -1
  289. mlrun/feature_store/retrieval/conversion.py +0 -273
  290. mlrun/kfpops.py +0 -868
  291. mlrun/model_monitoring/application.py +0 -310
  292. mlrun/model_monitoring/batch.py +0 -1095
  293. mlrun/model_monitoring/prometheus.py +0 -219
  294. mlrun/model_monitoring/stores/__init__.py +0 -111
  295. mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -576
  296. mlrun/model_monitoring/stores/model_endpoint_store.py +0 -147
  297. mlrun/model_monitoring/stores/models/__init__.py +0 -27
  298. mlrun/model_monitoring/stores/models/base.py +0 -84
  299. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -384
  300. mlrun/platforms/other.py +0 -306
  301. mlrun-1.6.4rc7.dist-info/METADATA +0 -272
  302. mlrun-1.6.4rc7.dist-info/RECORD +0 -314
  303. {mlrun-1.6.4rc7.dist-info → mlrun-1.7.0.dist-info}/LICENSE +0 -0
  304. {mlrun-1.6.4rc7.dist-info → mlrun-1.7.0.dist-info}/entry_points.txt +0 -0
  305. {mlrun-1.6.4rc7.dist-info → mlrun-1.7.0.dist-info}/top_level.txt +0 -0
mlrun/db/httpdb.py CHANGED
@@ -11,28 +11,36 @@
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 enum
15
16
  import http
16
17
  import re
17
- import tempfile
18
18
  import time
19
19
  import traceback
20
20
  import typing
21
21
  import warnings
22
+ from copy import deepcopy
22
23
  from datetime import datetime, timedelta
23
24
  from os import path, remove
24
- from typing import Dict, List, Optional, Union
25
+ from typing import Optional, Union
25
26
  from urllib.parse import urlparse
26
27
 
27
- import kfp
28
28
  import requests
29
29
  import semver
30
+ from mlrun_pipelines.utils import compile_pipeline
30
31
 
31
32
  import mlrun
33
+ import mlrun.common.formatters
34
+ import mlrun.common.runtimes
32
35
  import mlrun.common.schemas
36
+ import mlrun.common.types
33
37
  import mlrun.model_monitoring.model_endpoint
34
38
  import mlrun.platforms
35
39
  import mlrun.projects
40
+ import mlrun.runtimes.nuclio.api_gateway
41
+ import mlrun.runtimes.nuclio.function
42
+ import mlrun.utils
43
+ from mlrun.alerts.alert import AlertConfig
36
44
  from mlrun.db.auth_utils import OAuthClientIDTokenProvider, StaticTokenProvider
37
45
  from mlrun.errors import MLRunInvalidArgumentError, err_to_str
38
46
 
@@ -46,7 +54,6 @@ from ..utils import (
46
54
  datetime_to_iso,
47
55
  dict_to_json,
48
56
  logger,
49
- new_pipe_metadata,
50
57
  normalize_name,
51
58
  version,
52
59
  )
@@ -191,7 +198,7 @@ class HTTPRunDB(RunDBInterface):
191
198
  headers=None,
192
199
  timeout=45,
193
200
  version=None,
194
- ):
201
+ ) -> requests.Response:
195
202
  """Perform a direct REST API call on the :py:mod:`mlrun` API server.
196
203
 
197
204
  Caution:
@@ -209,7 +216,7 @@ class HTTPRunDB(RunDBInterface):
209
216
  :param version: API version to use, None (the default) will mean to use the default value from config,
210
217
  for un-versioned api set an empty string.
211
218
 
212
- :return: Python HTTP response object
219
+ :returns: `requests.Response` HTTP response object
213
220
  """
214
221
  url = self.get_base_api_url(path, version)
215
222
  kw = {
@@ -292,6 +299,68 @@ class HTTPRunDB(RunDBInterface):
292
299
 
293
300
  return response
294
301
 
302
+ def paginated_api_call(
303
+ self,
304
+ method,
305
+ path,
306
+ error=None,
307
+ params=None,
308
+ body=None,
309
+ json=None,
310
+ headers=None,
311
+ timeout=45,
312
+ version=None,
313
+ ) -> typing.Generator[requests.Response, None, None]:
314
+ """
315
+ Calls the api with pagination, yielding each page of the response
316
+ """
317
+
318
+ def _api_call(_params):
319
+ return self.api_call(
320
+ method=method,
321
+ path=path,
322
+ error=error,
323
+ params=_params,
324
+ body=body,
325
+ json=json,
326
+ headers=headers,
327
+ timeout=timeout,
328
+ version=version,
329
+ )
330
+
331
+ first_page_params = deepcopy(params) or {}
332
+ first_page_params["page"] = 1
333
+ first_page_params["page-size"] = config.httpdb.pagination.default_page_size
334
+ response = _api_call(first_page_params)
335
+ page_token = response.json().get("pagination", {}).get("page-token")
336
+ if not page_token:
337
+ yield response
338
+ return
339
+
340
+ params_with_page_token = deepcopy(params) or {}
341
+ params_with_page_token["page-token"] = page_token
342
+ while page_token:
343
+ yield response
344
+ try:
345
+ response = _api_call(params_with_page_token)
346
+ except mlrun.errors.MLRunNotFoundError:
347
+ # pagination token expired
348
+ break
349
+
350
+ page_token = response.json().get("pagination", {}).get("page-token", None)
351
+
352
+ @staticmethod
353
+ def process_paginated_responses(
354
+ responses: typing.Generator[requests.Response, None, None], key: str = "data"
355
+ ) -> list[typing.Any]:
356
+ """
357
+ Processes the paginated responses and returns the combined data
358
+ """
359
+ data = []
360
+ for response in responses:
361
+ data.extend(response.json().get(key, []))
362
+ return data
363
+
295
364
  def _init_session(self, retry_on_post: bool = False):
296
365
  return mlrun.utils.HTTPSessionWithRetry(
297
366
  retry_on_exception=config.httpdb.retry_api_call_on_exception
@@ -324,7 +393,7 @@ class HTTPRunDB(RunDBInterface):
324
393
 
325
394
  For example::
326
395
 
327
- config.dbpath = config.dbpath or 'http://mlrun-api:8080'
396
+ config.dbpath = config.dbpath or "http://mlrun-api:8080"
328
397
  db = get_run_db().connect()
329
398
  """
330
399
  # hack to allow unit tests to instantiate HTTPRunDB without a real server behind
@@ -456,14 +525,18 @@ class HTTPRunDB(RunDBInterface):
456
525
  server_cfg.get("external_platform_tracking")
457
526
  or config.external_platform_tracking
458
527
  )
459
- config.model_endpoint_monitoring.store_type = (
460
- server_cfg.get("model_endpoint_monitoring_store_type")
461
- or config.model_endpoint_monitoring.store_type
462
- )
463
528
  config.model_endpoint_monitoring.endpoint_store_connection = (
464
529
  server_cfg.get("model_endpoint_monitoring_endpoint_store_connection")
465
530
  or config.model_endpoint_monitoring.endpoint_store_connection
466
531
  )
532
+ config.model_endpoint_monitoring.tsdb_connection = (
533
+ server_cfg.get("model_monitoring_tsdb_connection")
534
+ or config.model_endpoint_monitoring.tsdb_connection
535
+ )
536
+ config.model_endpoint_monitoring.stream_connection = (
537
+ server_cfg.get("stream_connection")
538
+ or config.model_endpoint_monitoring.stream_connection
539
+ )
467
540
  config.packagers = server_cfg.get("packagers") or config.packagers
468
541
  server_data_prefixes = server_cfg.get("feature_store_data_prefixes") or {}
469
542
  for prefix in ["default", "nosql", "redisnosql"]:
@@ -472,6 +545,11 @@ class HTTPRunDB(RunDBInterface):
472
545
  setattr(
473
546
  config.feature_store.data_prefixes, prefix, server_prefix_value
474
547
  )
548
+ config.feature_store.default_targets = (
549
+ server_cfg.get("feature_store_default_targets")
550
+ or config.feature_store.default_targets
551
+ )
552
+ config.alerts.mode = server_cfg.get("alerts_mode") or config.alerts.mode
475
553
 
476
554
  except Exception as exc:
477
555
  logger.warning(
@@ -518,7 +596,7 @@ class HTTPRunDB(RunDBInterface):
518
596
  if offset < 0:
519
597
  raise MLRunInvalidArgumentError("Offset cannot be negative")
520
598
  if size is None:
521
- size = int(config.httpdb.logs.pull_logs_default_size_limit)
599
+ size = int(mlrun.mlconf.httpdb.logs.pull_logs_default_size_limit)
522
600
  elif size == -1:
523
601
  logger.warning(
524
602
  "Retrieving all logs. This may be inefficient and can result in a large log."
@@ -564,33 +642,35 @@ class HTTPRunDB(RunDBInterface):
564
642
 
565
643
  state, text = self.get_log(uid, project, offset=offset)
566
644
  if text:
567
- print(text.decode(errors=config.httpdb.logs.decode.errors))
645
+ print(text.decode(errors=mlrun.mlconf.httpdb.logs.decode.errors))
568
646
  nil_resp = 0
569
647
  while True:
570
648
  offset += len(text)
571
649
  # if we get 3 nil responses in a row, increase the sleep time to 10 seconds
572
650
  # TODO: refactor this to use a conditional backoff mechanism
573
651
  if nil_resp < 3:
574
- time.sleep(int(config.httpdb.logs.pull_logs_default_interval))
652
+ time.sleep(int(mlrun.mlconf.httpdb.logs.pull_logs_default_interval))
575
653
  else:
576
654
  time.sleep(
577
- int(config.httpdb.logs.pull_logs_backoff_no_logs_default_interval)
655
+ int(
656
+ mlrun.mlconf.httpdb.logs.pull_logs_backoff_no_logs_default_interval
657
+ )
578
658
  )
579
659
  state, text = self.get_log(uid, project, offset=offset)
580
660
  if text:
581
661
  nil_resp = 0
582
662
  print(
583
- text.decode(errors=config.httpdb.logs.decode.errors),
663
+ text.decode(errors=mlrun.mlconf.httpdb.logs.decode.errors),
584
664
  end="",
585
665
  )
586
666
  else:
587
667
  nil_resp += 1
588
668
 
589
669
  if watch and state in [
590
- mlrun.runtimes.constants.RunStates.pending,
591
- mlrun.runtimes.constants.RunStates.running,
592
- mlrun.runtimes.constants.RunStates.created,
593
- mlrun.runtimes.constants.RunStates.aborting,
670
+ mlrun.common.runtimes.constants.RunStates.pending,
671
+ mlrun.common.runtimes.constants.RunStates.running,
672
+ mlrun.common.runtimes.constants.RunStates.created,
673
+ mlrun.common.runtimes.constants.RunStates.aborting,
594
674
  ]:
595
675
  continue
596
676
  else:
@@ -651,7 +731,7 @@ class HTTPRunDB(RunDBInterface):
651
731
  uid,
652
732
  project="",
653
733
  iter=0,
654
- format_: mlrun.common.schemas.runs.RunsFormat = mlrun.common.schemas.runs.RunsFormat.full,
734
+ format_: mlrun.common.formatters.RunFormat = mlrun.common.formatters.RunFormat.full,
655
735
  ):
656
736
  """Read the details of a stored run from the DB.
657
737
 
@@ -686,10 +766,13 @@ class HTTPRunDB(RunDBInterface):
686
766
  def list_runs(
687
767
  self,
688
768
  name: Optional[str] = None,
689
- uid: Optional[Union[str, List[str]]] = None,
769
+ uid: Optional[Union[str, list[str]]] = None,
690
770
  project: Optional[str] = None,
691
- labels: Optional[Union[str, List[str]]] = None,
692
- state: Optional[str] = None,
771
+ labels: Optional[Union[str, list[str]]] = None,
772
+ state: Optional[
773
+ mlrun.common.runtimes.constants.RunStates
774
+ ] = None, # Backward compatibility
775
+ states: typing.Optional[list[mlrun.common.runtimes.constants.RunStates]] = None,
693
776
  sort: bool = True,
694
777
  last: int = 0,
695
778
  iter: bool = False,
@@ -714,9 +797,11 @@ class HTTPRunDB(RunDBInterface):
714
797
 
715
798
  Example::
716
799
 
717
- runs = db.list_runs(name='download', project='iris', labels=['owner=admin', 'kind=job'])
800
+ runs = db.list_runs(
801
+ name="download", project="iris", labels=["owner=admin", "kind=job"]
802
+ )
718
803
  # If running in Jupyter, can use the .show() function to display the results
719
- db.list_runs(name='', project=project_name).show()
804
+ db.list_runs(name="", project=project_name).show()
720
805
 
721
806
 
722
807
  :param name: Name of the run to retrieve.
@@ -725,7 +810,8 @@ class HTTPRunDB(RunDBInterface):
725
810
  :param labels: A list of labels to filter by. Label filters work by either filtering a specific value
726
811
  of a label (i.e. list("key=value")) or by looking for the existence of a given
727
812
  key (i.e. "key").
728
- :param state: List only runs whose state is specified.
813
+ :param state: Deprecated - List only runs whose state is specified (will be removed in 1.9.0)
814
+ :param states: List only runs whose state is one of the provided states.
729
815
  :param sort: Whether to sort the result according to their start time. Otherwise, results will be
730
816
  returned by their internal order in the DB (order will not be guaranteed).
731
817
  :param last: Deprecated - currently not used (will be removed in 1.8.0).
@@ -761,11 +847,19 @@ class HTTPRunDB(RunDBInterface):
761
847
  FutureWarning,
762
848
  )
763
849
 
850
+ if state:
851
+ # TODO: Remove this in 1.9.0
852
+ warnings.warn(
853
+ "'state' is deprecated and will be removed in 1.9.0. Use 'states' instead.",
854
+ FutureWarning,
855
+ )
856
+
764
857
  if (
765
858
  not name
766
859
  and not uid
767
860
  and not labels
768
861
  and not state
862
+ and not states
769
863
  and not last
770
864
  and not start_time_from
771
865
  and not start_time_to
@@ -777,14 +871,16 @@ class HTTPRunDB(RunDBInterface):
777
871
  ):
778
872
  # default to last week on no filter
779
873
  start_time_from = datetime.now() - timedelta(days=7)
780
- partition_by = mlrun.common.schemas.RunPartitionByField.name
874
+ partition_by = mlrun.common.schemas.RunPartitionByField.project_and_name
781
875
  partition_sort_by = mlrun.common.schemas.SortField.updated
782
876
 
783
877
  params = {
784
878
  "name": name,
785
879
  "uid": uid,
786
880
  "label": labels or [],
787
- "state": state,
881
+ "state": mlrun.utils.helpers.as_list(state)
882
+ if state is not None
883
+ else states or None,
788
884
  "sort": bool2str(sort),
789
885
  "iter": bool2str(iter),
790
886
  "start_time_from": datetime_to_iso(start_time_from),
@@ -807,15 +903,15 @@ class HTTPRunDB(RunDBInterface):
807
903
  )
808
904
  error = "list runs"
809
905
  _path = self._path_of("runs", project)
810
- resp = self.api_call("GET", _path, error, params=params)
811
- return RunList(resp.json()["runs"])
906
+ responses = self.paginated_api_call("GET", _path, error, params=params)
907
+ return RunList(self.process_paginated_responses(responses, "runs"))
812
908
 
813
909
  def del_runs(self, name=None, project=None, labels=None, state=None, days_ago=0):
814
910
  """Delete a group of runs identified by the parameters of the function.
815
911
 
816
912
  Example::
817
913
 
818
- db.del_runs(state='completed')
914
+ db.del_runs(state="completed")
819
915
 
820
916
  :param name: Name of the task which the runs belong to.
821
917
  :param project: Project to which the runs belong.
@@ -868,7 +964,7 @@ class HTTPRunDB(RunDBInterface):
868
964
 
869
965
  # we do this because previously the 'uid' name was used for the 'tree' parameter
870
966
  tree = tree or uid
871
-
967
+ project = project or mlrun.mlconf.default_project
872
968
  endpoint_path = f"projects/{project}/artifacts/{key}"
873
969
 
874
970
  error = f"store artifact {project}/{key}"
@@ -894,6 +990,7 @@ class HTTPRunDB(RunDBInterface):
894
990
  project="",
895
991
  tree=None,
896
992
  uid=None,
993
+ format_: mlrun.common.formatters.ArtifactFormat = mlrun.common.formatters.ArtifactFormat.full,
897
994
  ):
898
995
  """Read an artifact, identified by its key, tag, tree and iteration.
899
996
 
@@ -903,25 +1000,37 @@ class HTTPRunDB(RunDBInterface):
903
1000
  :param project: Project that the artifact belongs to.
904
1001
  :param tree: The tree which generated this artifact.
905
1002
  :param uid: A unique ID for this specific version of the artifact (the uid that was generated in the backend)
1003
+ :param format_: The format in which to return the artifact. Default is 'full'.
906
1004
  """
907
1005
 
908
- project = project or config.default_project
1006
+ project = project or mlrun.mlconf.default_project
909
1007
  tag = tag or "latest"
910
1008
  endpoint_path = f"projects/{project}/artifacts/{key}"
911
1009
  error = f"read artifact {project}/{key}"
912
- # explicitly set artifacts format to 'full' since old servers may default to 'legacy'
913
1010
  params = {
914
- "format": mlrun.common.schemas.ArtifactsFormat.full.value,
1011
+ "format": format_,
915
1012
  "tag": tag,
916
1013
  "tree": tree,
917
- "uid": uid,
1014
+ "object-uid": uid,
918
1015
  }
919
- if iter:
1016
+ if iter is not None:
920
1017
  params["iter"] = str(iter)
921
1018
  resp = self.api_call("GET", endpoint_path, error, params=params, version="v2")
922
1019
  return resp.json()
923
1020
 
924
- def del_artifact(self, key, tag=None, project="", tree=None, uid=None):
1021
+ def del_artifact(
1022
+ self,
1023
+ key,
1024
+ tag=None,
1025
+ project="",
1026
+ tree=None,
1027
+ uid=None,
1028
+ deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
1029
+ mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
1030
+ ),
1031
+ secrets: dict = None,
1032
+ iter=None,
1033
+ ):
925
1034
  """Delete an artifact.
926
1035
 
927
1036
  :param key: Identifying key of the artifact.
@@ -929,32 +1038,44 @@ class HTTPRunDB(RunDBInterface):
929
1038
  :param project: Project that the artifact belongs to.
930
1039
  :param tree: The tree which generated this artifact.
931
1040
  :param uid: A unique ID for this specific version of the artifact (the uid that was generated in the backend)
1041
+ :param deletion_strategy: The artifact deletion strategy types.
1042
+ :param secrets: Credentials needed to access the artifact data.
932
1043
  """
933
-
1044
+ project = project or mlrun.mlconf.default_project
934
1045
  endpoint_path = f"projects/{project}/artifacts/{key}"
935
1046
  params = {
936
1047
  "key": key,
937
1048
  "tag": tag,
938
1049
  "tree": tree,
939
- "uid": uid,
1050
+ "object-uid": uid,
1051
+ "iter": iter,
1052
+ "deletion_strategy": deletion_strategy,
940
1053
  }
941
1054
  error = f"del artifact {project}/{key}"
942
- self.api_call("DELETE", endpoint_path, error, params=params, version="v2")
1055
+ self.api_call(
1056
+ "DELETE",
1057
+ endpoint_path,
1058
+ error,
1059
+ params=params,
1060
+ version="v2",
1061
+ body=dict_to_json(secrets),
1062
+ )
943
1063
 
944
1064
  def list_artifacts(
945
1065
  self,
946
1066
  name=None,
947
1067
  project=None,
948
1068
  tag=None,
949
- labels: Optional[Union[Dict[str, str], List[str]]] = None,
950
- since=None,
951
- until=None,
1069
+ labels: Optional[Union[dict[str, str], list[str]]] = None,
1070
+ since: Optional[datetime] = None,
1071
+ until: Optional[datetime] = None,
952
1072
  iter: int = None,
953
1073
  best_iteration: bool = False,
954
1074
  kind: str = None,
955
1075
  category: Union[str, mlrun.common.schemas.ArtifactCategories] = None,
956
1076
  tree: str = None,
957
1077
  producer_uri: str = None,
1078
+ format_: mlrun.common.formatters.ArtifactFormat = mlrun.common.formatters.ArtifactFormat.full,
958
1079
  limit: int = None,
959
1080
  ) -> ArtifactList:
960
1081
  """List artifacts filtered by various parameters.
@@ -962,11 +1083,13 @@ class HTTPRunDB(RunDBInterface):
962
1083
  Examples::
963
1084
 
964
1085
  # Show latest version of all artifacts in project
965
- latest_artifacts = db.list_artifacts('', tag='latest', project='iris')
1086
+ latest_artifacts = db.list_artifacts("", tag="latest", project="iris")
966
1087
  # check different artifact versions for a specific artifact
967
- result_versions = db.list_artifacts('results', tag='*', project='iris')
1088
+ result_versions = db.list_artifacts("results", tag="*", project="iris")
968
1089
  # Show artifacts with label filters - both uploaded and of binary type
969
- result_labels = db.list_artifacts('results', tag='*', project='iris', labels=['uploaded', 'type=binary'])
1090
+ result_labels = db.list_artifacts(
1091
+ "results", tag="*", project="iris", labels=["uploaded", "type=binary"]
1092
+ )
970
1093
 
971
1094
  :param name: Name of artifacts to retrieve. Name with '~' prefix is used as a like query, and is not
972
1095
  case-sensitive. This means that querying for ``~name`` may return artifacts named
@@ -975,8 +1098,8 @@ class HTTPRunDB(RunDBInterface):
975
1098
  :param tag: Return artifacts assigned this tag.
976
1099
  :param labels: Return artifacts that have these labels. Labels can either be a dictionary {"label": "value"} or
977
1100
  a list of "label=value" (match label key and value) or "label" (match just label key) strings.
978
- :param since: Not in use in :py:class:`HTTPRunDB`.
979
- :param until: Not in use in :py:class:`HTTPRunDB`.
1101
+ :param since: Return artifacts updated after this date (as datetime object).
1102
+ :param until: Return artifacts updated before this date (as datetime object).
980
1103
  :param iter: Return artifacts from a specific iteration (where ``iter=0`` means the root iteration). If
981
1104
  ``None`` (default) return artifacts from all iterations.
982
1105
  :param best_iteration: Returns the artifact which belongs to the best iteration of a given run, in the case of
@@ -988,6 +1111,7 @@ class HTTPRunDB(RunDBInterface):
988
1111
  :param producer_uri: Return artifacts produced by the requested producer URI. Producer URI usually
989
1112
  points to a run and is used to filter artifacts by the run that produced them when the artifact producer id
990
1113
  is a workflow id (artifact was created as part of a workflow).
1114
+ :param format_: The format in which to return the artifacts. Default is 'full'.
991
1115
  :param limit: Maximum number of artifacts to return.
992
1116
  """
993
1117
 
@@ -1006,9 +1130,11 @@ class HTTPRunDB(RunDBInterface):
1006
1130
  "kind": kind,
1007
1131
  "category": category,
1008
1132
  "tree": tree,
1009
- "format": mlrun.common.schemas.ArtifactsFormat.full.value,
1133
+ "format": format_,
1010
1134
  "producer_uri": producer_uri,
1011
1135
  "limit": limit,
1136
+ "since": datetime_to_iso(since),
1137
+ "until": datetime_to_iso(until),
1012
1138
  }
1013
1139
  error = "list artifacts"
1014
1140
  endpoint_path = f"projects/{project}/artifacts"
@@ -1045,7 +1171,7 @@ class HTTPRunDB(RunDBInterface):
1045
1171
  self,
1046
1172
  project=None,
1047
1173
  category: Union[str, mlrun.common.schemas.ArtifactCategories] = None,
1048
- ) -> List[str]:
1174
+ ) -> list[str]:
1049
1175
  """Return a list of all the tags assigned to artifacts in the scope of the given project."""
1050
1176
 
1051
1177
  project = project or config.default_project
@@ -1098,15 +1224,44 @@ class HTTPRunDB(RunDBInterface):
1098
1224
  project = project or config.default_project
1099
1225
  path = f"projects/{project}/functions/{name}"
1100
1226
  error_message = f"Failed deleting function {project}/{name}"
1101
- self.api_call("DELETE", path, error_message)
1227
+ response = self.api_call("DELETE", path, error_message, version="v2")
1228
+ if response.status_code == http.HTTPStatus.ACCEPTED:
1229
+ logger.info(
1230
+ "Function is being deleted", project_name=project, function_name=name
1231
+ )
1232
+ background_task = mlrun.common.schemas.BackgroundTask(**response.json())
1233
+ background_task = self._wait_for_background_task_to_reach_terminal_state(
1234
+ background_task.metadata.name, project=project
1235
+ )
1236
+ if (
1237
+ background_task.status.state
1238
+ == mlrun.common.schemas.BackgroundTaskState.succeeded
1239
+ ):
1240
+ logger.info(
1241
+ "Function deleted", project_name=project, function_name=name
1242
+ )
1243
+ elif (
1244
+ background_task.status.state
1245
+ == mlrun.common.schemas.BackgroundTaskState.failed
1246
+ ):
1247
+ logger.info(
1248
+ "Function deletion failed",
1249
+ reason=background_task.status.error,
1250
+ project_name=project,
1251
+ function_name=name,
1252
+ )
1102
1253
 
1103
- def list_functions(self, name=None, project=None, tag=None, labels=None):
1254
+ def list_functions(
1255
+ self, name=None, project=None, tag=None, labels=None, since=None, until=None
1256
+ ):
1104
1257
  """Retrieve a list of functions, filtered by specific criteria.
1105
1258
 
1106
1259
  :param name: Return only functions with a specific name.
1107
1260
  :param project: Return functions belonging to this project. If not specified, the default project is used.
1108
- :param tag: Return function versions with specific tags.
1261
+ :param tag: Return function versions with specific tags. To return only tagged functions, set tag to ``"*"``.
1109
1262
  :param labels: Return functions that have specific labels assigned to them.
1263
+ :param since: Return functions updated after this date (as datetime object).
1264
+ :param until: Return functions updated before this date (as datetime object).
1110
1265
  :returns: List of function objects (as dictionary).
1111
1266
  """
1112
1267
  project = project or config.default_project
@@ -1114,11 +1269,13 @@ class HTTPRunDB(RunDBInterface):
1114
1269
  "name": name,
1115
1270
  "tag": tag,
1116
1271
  "label": labels or [],
1272
+ "since": datetime_to_iso(since),
1273
+ "until": datetime_to_iso(until),
1117
1274
  }
1118
1275
  error = "list functions"
1119
1276
  path = f"projects/{project}/functions"
1120
- resp = self.api_call("GET", path, error, params=params)
1121
- return resp.json()["funcs"]
1277
+ responses = self.paginated_api_call("GET", path, error, params=params)
1278
+ return self.process_paginated_responses(responses, "funcs")
1122
1279
 
1123
1280
  def list_runtime_resources(
1124
1281
  self,
@@ -1208,25 +1365,19 @@ class HTTPRunDB(RunDBInterface):
1208
1365
  period didn't pass.
1209
1366
  :param grace_period: Grace period given to the runtime resource before they are actually removed, counted from
1210
1367
  the moment they moved to terminal state
1211
- (defaults to mlrun.config.config.runtime_resources_deletion_grace_period).
1368
+ (defaults to mlrun.mlconf.runtime_resources_deletion_grace_period).
1212
1369
 
1213
1370
  :returns: :py:class:`~mlrun.common.schemas.GroupedByProjectRuntimeResourcesOutput` listing the runtime resources
1214
1371
  that were removed.
1215
1372
  """
1216
- if grace_period is None:
1217
- grace_period = config.runtime_resources_deletion_grace_period
1218
- logger.info(
1219
- "Using default grace period for runtime resources deletion",
1220
- grace_period=grace_period,
1221
- )
1222
-
1223
1373
  params = {
1224
1374
  "label-selector": label_selector,
1225
1375
  "kind": kind,
1226
1376
  "object-id": object_id,
1227
1377
  "force": force,
1228
- "grace-period": grace_period,
1229
1378
  }
1379
+ if grace_period is not None:
1380
+ params["grace-period"] = grace_period
1230
1381
  error = "Failed deleting runtime resources"
1231
1382
  project_path = project if project else "*"
1232
1383
  response = self.api_call(
@@ -1264,7 +1415,9 @@ class HTTPRunDB(RunDBInterface):
1264
1415
  name="run_func_on_tuesdays",
1265
1416
  kind="job",
1266
1417
  scheduled_object=get_data_func,
1267
- cron_trigger=schemas.ScheduleCronTrigger(day_of_week='tue', hour=15, minute=30),
1418
+ cron_trigger=schemas.ScheduleCronTrigger(
1419
+ day_of_week="tue", hour=15, minute=30
1420
+ ),
1268
1421
  )
1269
1422
  db.create_schedule(project_name, schedule)
1270
1423
  """
@@ -1367,21 +1520,7 @@ class HTTPRunDB(RunDBInterface):
1367
1520
  :param builder_env: Kaniko builder pod env vars dict (for config/credentials)
1368
1521
  :param force_build: Force building the image, even when no changes were made
1369
1522
  """
1370
- is_s3_source = func.spec.build.source and func.spec.build.source.startswith(
1371
- "s3://"
1372
- )
1373
- is_ecr_image = mlrun.utils.is_ecr_url(config.httpdb.builder.docker_registry)
1374
- if not func.spec.build.load_source_on_run and is_s3_source and is_ecr_image:
1375
- logger.warning(
1376
- "Building a function image to ECR and loading an S3 source to the image may require conflicting access "
1377
- "keys. Only the permissions granted to the platform's configured secret will take affect "
1378
- "(see mlrun.config.config.httpdb.builder.docker_registry_secret). "
1379
- "In case the permissions are limited to ECR scope, you may use pull_at_runtime=True instead",
1380
- source=func.spec.build.source,
1381
- load_source_on_run=func.spec.build.load_source_on_run,
1382
- default_docker_registry=config.httpdb.builder.docker_registry,
1383
- )
1384
-
1523
+ self.warn_on_s3_and_ecr_permissions_conflict(func)
1385
1524
  try:
1386
1525
  req = {
1387
1526
  "function": func.to_dict(),
@@ -1400,10 +1539,94 @@ class HTTPRunDB(RunDBInterface):
1400
1539
 
1401
1540
  if not resp.ok:
1402
1541
  logger.error(f"bad resp!!\n{resp.text}")
1403
- raise ValueError("bad function run response")
1542
+ raise ValueError("bad submit build response")
1404
1543
 
1405
1544
  return resp.json()
1406
1545
 
1546
+ def deploy_nuclio_function(
1547
+ self,
1548
+ func: mlrun.runtimes.RemoteRuntime,
1549
+ builder_env: Optional[dict] = None,
1550
+ ):
1551
+ """
1552
+ Deploy a Nuclio function.
1553
+
1554
+ :param func: Function to build.
1555
+ :param builder_env: Kaniko builder pod env vars dict (for config/credentials)
1556
+ """
1557
+ func.metadata.project = func.metadata.project or config.default_project
1558
+ self.warn_on_s3_and_ecr_permissions_conflict(func)
1559
+ try:
1560
+ req = {
1561
+ "function": func.to_dict(),
1562
+ }
1563
+ if builder_env:
1564
+ req["builder_env"] = builder_env
1565
+ _path = (
1566
+ f"projects/{func.metadata.project}/nuclio/{func.metadata.name}/deploy"
1567
+ )
1568
+ resp = self.api_call("POST", _path, json=req)
1569
+ except OSError as err:
1570
+ logger.error(f"error submitting nuclio deploy task: {err_to_str(err)}")
1571
+ raise OSError(f"error: cannot submit deploy, {err_to_str(err)}")
1572
+
1573
+ if not resp.ok:
1574
+ logger.error(f"deploy nuclio - bad response:\n{resp.text}")
1575
+ raise ValueError("bad nuclio deploy response")
1576
+
1577
+ return resp.json()
1578
+
1579
+ def get_nuclio_deploy_status(
1580
+ self,
1581
+ func: mlrun.runtimes.RemoteRuntime,
1582
+ last_log_timestamp: float = 0.0,
1583
+ verbose: bool = False,
1584
+ ):
1585
+ """Retrieve the status of a deploy operation currently in progress.
1586
+
1587
+ :param func: Function object that is being built.
1588
+ :param last_log_timestamp: Last timestamp of logs that were already retrieved. Function will return only logs
1589
+ later than this parameter.
1590
+ :param verbose: Add verbose logs into the output.
1591
+
1592
+ :returns: The following parameters:
1593
+
1594
+ - Text of builder logs.
1595
+ - Timestamp of last log retrieved, to be used in subsequent calls to this function.
1596
+ """
1597
+
1598
+ try:
1599
+ normalized_name = normalize_name(func.metadata.name)
1600
+ params = {
1601
+ "name": normalized_name,
1602
+ "project": func.metadata.project,
1603
+ "tag": func.metadata.tag,
1604
+ "last_log_timestamp": str(last_log_timestamp),
1605
+ "verbose": bool2str(verbose),
1606
+ }
1607
+ _path = f"projects/{func.metadata.project}/nuclio/{normalized_name}/deploy"
1608
+ resp = self.api_call("GET", _path, params=params)
1609
+ except OSError as err:
1610
+ logger.error(f"error getting deploy status: {err_to_str(err)}")
1611
+ raise OSError(f"error: cannot get deploy status, {err_to_str(err)}")
1612
+
1613
+ if not resp.ok:
1614
+ logger.warning(f"failed resp, {resp.text}")
1615
+ raise RunDBError("bad function build response")
1616
+
1617
+ if resp.headers:
1618
+ last_log_timestamp = float(
1619
+ resp.headers.get("x-mlrun-last-timestamp", "0.0")
1620
+ )
1621
+ mlrun.runtimes.nuclio.function.enrich_nuclio_function_from_headers(
1622
+ func, resp.headers
1623
+ )
1624
+
1625
+ text = ""
1626
+ if resp.content:
1627
+ text = resp.content.decode()
1628
+ return text, last_log_timestamp
1629
+
1407
1630
  def get_builder_status(
1408
1631
  self,
1409
1632
  func: BaseRuntime,
@@ -1453,21 +1676,18 @@ class HTTPRunDB(RunDBInterface):
1453
1676
  last_log_timestamp = float(
1454
1677
  resp.headers.get("x-mlrun-last-timestamp", "0.0")
1455
1678
  )
1456
- if func.kind in mlrun.runtimes.RuntimeKinds.nuclio_runtimes():
1457
- func.status.address = resp.headers.get("x-mlrun-address", "")
1458
- func.status.nuclio_name = resp.headers.get("x-mlrun-name", "")
1459
- func.status.internal_invocation_urls = resp.headers.get(
1460
- "x-mlrun-internal-invocation-urls", ""
1461
- ).split(",")
1462
- func.status.external_invocation_urls = resp.headers.get(
1463
- "x-mlrun-external-invocation-urls", ""
1464
- ).split(",")
1465
- func.status.container_image = resp.headers.get(
1466
- "x-mlrun-container-image", ""
1679
+ if func.kind in mlrun.runtimes.RuntimeKinds.pure_nuclio_deployed_runtimes():
1680
+ mlrun.runtimes.nuclio.function.enrich_nuclio_function_from_headers(
1681
+ func, resp.headers
1467
1682
  )
1468
- else:
1469
- func.status.build_pod = resp.headers.get("builder_pod", "")
1470
- func.spec.image = resp.headers.get("function_image", "")
1683
+
1684
+ builder_pod = resp.headers.get("builder_pod", "")
1685
+ if builder_pod:
1686
+ func.status.build_pod = builder_pod
1687
+
1688
+ function_image = resp.headers.get("function_image", "")
1689
+ if function_image:
1690
+ func.spec.image = function_image
1471
1691
 
1472
1692
  text = ""
1473
1693
  if resp.content:
@@ -1530,7 +1750,7 @@ class HTTPRunDB(RunDBInterface):
1530
1750
  Retrieve updated information on project background tasks being executed.
1531
1751
  If no filter is provided, will return background tasks from the last week.
1532
1752
 
1533
- :param project: Project name (defaults to mlrun.config.config.default_project).
1753
+ :param project: Project name (defaults to mlrun.mlconf.default_project).
1534
1754
  :param state: List only background tasks whose state is specified.
1535
1755
  :param created_from: Filter by background task created time in ``[created_from, created_to]``.
1536
1756
  :param created_to: Filter by background task created time in ``[created_from, created_to]``.
@@ -1663,14 +1883,11 @@ class HTTPRunDB(RunDBInterface):
1663
1883
  if isinstance(pipeline, str):
1664
1884
  pipe_file = pipeline
1665
1885
  else:
1666
- pipe_file = tempfile.NamedTemporaryFile(suffix=".yaml", delete=False).name
1667
- conf = new_pipe_metadata(
1886
+ pipe_file = compile_pipeline(
1668
1887
  artifact_path=artifact_path,
1669
1888
  cleanup_ttl=cleanup_ttl,
1670
- op_transformers=ops,
1671
- )
1672
- kfp.compiler.Compiler().compile(
1673
- pipeline, pipe_file, type_check=False, pipeline_conf=conf
1889
+ ops=ops,
1890
+ pipeline=pipeline,
1674
1891
  )
1675
1892
 
1676
1893
  if pipe_file.endswith(".yaml"):
@@ -1725,8 +1942,8 @@ class HTTPRunDB(RunDBInterface):
1725
1942
  page_token: str = "",
1726
1943
  filter_: str = "",
1727
1944
  format_: Union[
1728
- str, mlrun.common.schemas.PipelinesFormat
1729
- ] = mlrun.common.schemas.PipelinesFormat.metadata_only,
1945
+ str, mlrun.common.formatters.PipelineFormat
1946
+ ] = mlrun.common.formatters.PipelineFormat.metadata_only,
1730
1947
  page_size: int = None,
1731
1948
  ) -> mlrun.common.schemas.PipelinesOutput:
1732
1949
  """Retrieve a list of KFP pipelines. This function can be invoked to get all pipelines from all projects,
@@ -1772,8 +1989,8 @@ class HTTPRunDB(RunDBInterface):
1772
1989
  namespace: str = None,
1773
1990
  timeout: int = 30,
1774
1991
  format_: Union[
1775
- str, mlrun.common.schemas.PipelinesFormat
1776
- ] = mlrun.common.schemas.PipelinesFormat.summary,
1992
+ str, mlrun.common.formatters.PipelineFormat
1993
+ ] = mlrun.common.formatters.PipelineFormat.summary,
1777
1994
  project: str = None,
1778
1995
  ):
1779
1996
  """Retrieve details of a specific pipeline using its run ID (as provided when the pipeline was executed)."""
@@ -1865,9 +2082,9 @@ class HTTPRunDB(RunDBInterface):
1865
2082
  project: str,
1866
2083
  name: str = None,
1867
2084
  tag: str = None,
1868
- entities: List[str] = None,
1869
- labels: List[str] = None,
1870
- ) -> List[dict]:
2085
+ entities: list[str] = None,
2086
+ labels: list[str] = None,
2087
+ ) -> list[dict]:
1871
2088
  """List feature-sets which contain specific features. This function may return multiple versions of the same
1872
2089
  feature-set if a specific tag is not requested. Note that the various filters of this function actually
1873
2090
  refer to the feature-set object containing the features, not to the features themselves.
@@ -1897,13 +2114,48 @@ class HTTPRunDB(RunDBInterface):
1897
2114
  resp = self.api_call("GET", path, error_message, params=params)
1898
2115
  return resp.json()["features"]
1899
2116
 
2117
+ def list_features_v2(
2118
+ self,
2119
+ project: str,
2120
+ name: str = None,
2121
+ tag: str = None,
2122
+ entities: list[str] = None,
2123
+ labels: list[str] = None,
2124
+ ) -> dict[str, list[dict]]:
2125
+ """List feature-sets which contain specific features. This function may return multiple versions of the same
2126
+ feature-set if a specific tag is not requested. Note that the various filters of this function actually
2127
+ refer to the feature-set object containing the features, not to the features themselves.
2128
+
2129
+ :param project: Project which contains these features.
2130
+ :param name: Name of the feature to look for. The name is used in a like query, and is not case-sensitive. For
2131
+ example, looking for ``feat`` will return features which are named ``MyFeature`` as well as ``defeat``.
2132
+ :param tag: Return feature-sets which contain the features looked for, and are tagged with the specific tag.
2133
+ :param entities: Return only feature-sets which contain an entity whose name is contained in this list.
2134
+ :param labels: Return only feature-sets which are labeled as requested.
2135
+ :returns: A list of features, and a list of their corresponding feature sets.
2136
+ """
2137
+
2138
+ project = project or config.default_project
2139
+ params = {
2140
+ "name": name,
2141
+ "tag": tag,
2142
+ "entity": entities or [],
2143
+ "label": labels or [],
2144
+ }
2145
+
2146
+ path = f"projects/{project}/features"
2147
+
2148
+ error_message = f"Failed listing features, project: {project}, query: {params}"
2149
+ resp = self.api_call("GET", path, error_message, params=params, version="v2")
2150
+ return resp.json()
2151
+
1900
2152
  def list_entities(
1901
2153
  self,
1902
2154
  project: str,
1903
2155
  name: str = None,
1904
2156
  tag: str = None,
1905
- labels: List[str] = None,
1906
- ) -> List[dict]:
2157
+ labels: list[str] = None,
2158
+ ) -> list[dict]:
1907
2159
  """Retrieve a list of entities and their mapping to the containing feature-sets. This function is similar
1908
2160
  to the :py:func:`~list_features` function, and uses the same logic. However, the entities are matched
1909
2161
  against the name rather than the features.
@@ -1922,6 +2174,31 @@ class HTTPRunDB(RunDBInterface):
1922
2174
  resp = self.api_call("GET", path, error_message, params=params)
1923
2175
  return resp.json()["entities"]
1924
2176
 
2177
+ def list_entities_v2(
2178
+ self,
2179
+ project: str,
2180
+ name: str = None,
2181
+ tag: str = None,
2182
+ labels: list[str] = None,
2183
+ ) -> dict[str, list[dict]]:
2184
+ """Retrieve a list of entities and their mapping to the containing feature-sets. This function is similar
2185
+ to the :py:func:`~list_features_v2` function, and uses the same logic. However, the entities are matched
2186
+ against the name rather than the features.
2187
+ """
2188
+
2189
+ project = project or config.default_project
2190
+ params = {
2191
+ "name": name,
2192
+ "tag": tag,
2193
+ "label": labels or [],
2194
+ }
2195
+
2196
+ path = f"projects/{project}/entities"
2197
+
2198
+ error_message = f"Failed listing entities, project: {project}, query: {params}"
2199
+ resp = self.api_call("GET", path, error_message, params=params, version="v2")
2200
+ return resp.json()
2201
+
1925
2202
  @staticmethod
1926
2203
  def _generate_partition_by_params(
1927
2204
  partition_by_cls,
@@ -1947,9 +2224,9 @@ class HTTPRunDB(RunDBInterface):
1947
2224
  name: str = None,
1948
2225
  tag: str = None,
1949
2226
  state: str = None,
1950
- entities: List[str] = None,
1951
- features: List[str] = None,
1952
- labels: List[str] = None,
2227
+ entities: list[str] = None,
2228
+ features: list[str] = None,
2229
+ labels: list[str] = None,
1953
2230
  partition_by: Union[
1954
2231
  mlrun.common.schemas.FeatureStorePartitionByField, str
1955
2232
  ] = None,
@@ -1958,7 +2235,10 @@ class HTTPRunDB(RunDBInterface):
1958
2235
  partition_order: Union[
1959
2236
  mlrun.common.schemas.OrderType, str
1960
2237
  ] = mlrun.common.schemas.OrderType.desc,
1961
- ) -> List[FeatureSet]:
2238
+ format_: Union[
2239
+ str, mlrun.common.formatters.FeatureSetFormat
2240
+ ] = mlrun.common.formatters.FeatureSetFormat.full,
2241
+ ) -> list[FeatureSet]:
1962
2242
  """Retrieve a list of feature-sets matching the criteria provided.
1963
2243
 
1964
2244
  :param project: Project name.
@@ -1975,6 +2255,9 @@ class HTTPRunDB(RunDBInterface):
1975
2255
  :param partition_sort_by: What field to sort the results by, within each partition defined by `partition_by`.
1976
2256
  Currently the only allowed value are `created` and `updated`.
1977
2257
  :param partition_order: Order of sorting within partitions - `asc` or `desc`. Default is `desc`.
2258
+ :param format_: Format of the results. Possible values are:
2259
+ - ``minimal`` - Return minimal feature set objects, not including stats and preview for each feature set.
2260
+ - ``full`` - Return full feature set objects.
1978
2261
  :returns: List of matching :py:class:`~mlrun.feature_store.FeatureSet` objects.
1979
2262
  """
1980
2263
 
@@ -1987,6 +2270,7 @@ class HTTPRunDB(RunDBInterface):
1987
2270
  "entity": entities or [],
1988
2271
  "feature": features or [],
1989
2272
  "label": labels or [],
2273
+ "format": format_,
1990
2274
  }
1991
2275
  if partition_by:
1992
2276
  params.update(
@@ -2073,7 +2357,7 @@ class HTTPRunDB(RunDBInterface):
2073
2357
  not a full object.
2074
2358
  Example::
2075
2359
 
2076
- feature_set_update = {"status": {"processed" : True}}
2360
+ feature_set_update = {"status": {"processed": True}}
2077
2361
 
2078
2362
  Will apply the field ``status.processed`` to the existing object.
2079
2363
  :param project: Project which contains the modified object.
@@ -2168,7 +2452,7 @@ class HTTPRunDB(RunDBInterface):
2168
2452
  name: str = None,
2169
2453
  tag: str = None,
2170
2454
  state: str = None,
2171
- labels: List[str] = None,
2455
+ labels: list[str] = None,
2172
2456
  partition_by: Union[
2173
2457
  mlrun.common.schemas.FeatureStorePartitionByField, str
2174
2458
  ] = None,
@@ -2177,7 +2461,7 @@ class HTTPRunDB(RunDBInterface):
2177
2461
  partition_order: Union[
2178
2462
  mlrun.common.schemas.OrderType, str
2179
2463
  ] = mlrun.common.schemas.OrderType.desc,
2180
- ) -> List[FeatureVector]:
2464
+ ) -> list[FeatureVector]:
2181
2465
  """Retrieve a list of feature-vectors matching the criteria provided.
2182
2466
 
2183
2467
  :param project: Project name.
@@ -2379,7 +2663,7 @@ class HTTPRunDB(RunDBInterface):
2379
2663
 
2380
2664
  def tag_artifacts(
2381
2665
  self,
2382
- artifacts: Union[List[Artifact], List[dict], Artifact, dict],
2666
+ artifacts: Union[list[Artifact], list[dict], Artifact, dict],
2383
2667
  project: str,
2384
2668
  tag_name: str,
2385
2669
  replace: bool = False,
@@ -2415,11 +2699,11 @@ class HTTPRunDB(RunDBInterface):
2415
2699
  self,
2416
2700
  owner: str = None,
2417
2701
  format_: Union[
2418
- str, mlrun.common.schemas.ProjectsFormat
2419
- ] = mlrun.common.schemas.ProjectsFormat.name_only,
2420
- labels: List[str] = None,
2702
+ str, mlrun.common.formatters.ProjectFormat
2703
+ ] = mlrun.common.formatters.ProjectFormat.name_only,
2704
+ labels: list[str] = None,
2421
2705
  state: Union[str, mlrun.common.schemas.ProjectState] = None,
2422
- ) -> List[Union[mlrun.projects.MlrunProject, str]]:
2706
+ ) -> list[Union[mlrun.projects.MlrunProject, str]]:
2423
2707
  """Return a list of the existing projects, potentially filtered by specific criteria.
2424
2708
 
2425
2709
  :param owner: List only projects belonging to this specific owner.
@@ -2442,7 +2726,7 @@ class HTTPRunDB(RunDBInterface):
2442
2726
 
2443
2727
  error_message = f"Failed listing projects, query: {params}"
2444
2728
  response = self.api_call("GET", "projects", error_message, params=params)
2445
- if format_ == mlrun.common.schemas.ProjectsFormat.name_only:
2729
+ if format_ == mlrun.common.formatters.ProjectFormat.name_only:
2446
2730
  # projects is just a list of strings
2447
2731
  return response.json()["projects"]
2448
2732
 
@@ -2470,7 +2754,7 @@ class HTTPRunDB(RunDBInterface):
2470
2754
  deletion_strategy: Union[
2471
2755
  str, mlrun.common.schemas.DeletionStrategy
2472
2756
  ] = mlrun.common.schemas.DeletionStrategy.default(),
2473
- ):
2757
+ ) -> None:
2474
2758
  """Delete a project.
2475
2759
 
2476
2760
  :param name: Name of the project to delete.
@@ -2489,7 +2773,7 @@ class HTTPRunDB(RunDBInterface):
2489
2773
  "DELETE", f"projects/{name}", error_message, headers=headers, version="v2"
2490
2774
  )
2491
2775
  if response.status_code == http.HTTPStatus.ACCEPTED:
2492
- logger.info("Project is being deleted", project_name=name)
2776
+ logger.info("Waiting for project to be deleted", project_name=name)
2493
2777
  background_task = mlrun.common.schemas.BackgroundTask(**response.json())
2494
2778
  background_task = self._wait_for_background_task_to_reach_terminal_state(
2495
2779
  background_task.metadata.name
@@ -2499,10 +2783,17 @@ class HTTPRunDB(RunDBInterface):
2499
2783
  == mlrun.common.schemas.BackgroundTaskState.succeeded
2500
2784
  ):
2501
2785
  logger.info("Project deleted", project_name=name)
2502
- return
2786
+ elif (
2787
+ background_task.status.state
2788
+ == mlrun.common.schemas.BackgroundTaskState.failed
2789
+ ):
2790
+ logger.error(
2791
+ "Project deletion failed",
2792
+ project_name=name,
2793
+ error=background_task.status.error,
2794
+ )
2503
2795
  elif response.status_code == http.HTTPStatus.NO_CONTENT:
2504
2796
  logger.info("Project deleted", project_name=name)
2505
- return
2506
2797
 
2507
2798
  def store_project(
2508
2799
  self,
@@ -2647,11 +2938,11 @@ class HTTPRunDB(RunDBInterface):
2647
2938
  :param secrets: A set of secret values to store.
2648
2939
  Example::
2649
2940
 
2650
- secrets = {'password': 'myPassw0rd', 'aws_key': '111222333'}
2941
+ secrets = {"password": "myPassw0rd", "aws_key": "111222333"}
2651
2942
  db.create_project_secrets(
2652
2943
  "project1",
2653
2944
  provider=mlrun.common.schemas.SecretProviderName.kubernetes,
2654
- secrets=secrets
2945
+ secrets=secrets,
2655
2946
  )
2656
2947
  """
2657
2948
  path = f"projects/{project}/secrets"
@@ -2674,7 +2965,7 @@ class HTTPRunDB(RunDBInterface):
2674
2965
  provider: Union[
2675
2966
  str, mlrun.common.schemas.SecretProviderName
2676
2967
  ] = mlrun.common.schemas.SecretProviderName.kubernetes,
2677
- secrets: List[str] = None,
2968
+ secrets: list[str] = None,
2678
2969
  ) -> mlrun.common.schemas.SecretsData:
2679
2970
  """Retrieve project-context secrets from Vault.
2680
2971
 
@@ -2763,7 +3054,7 @@ class HTTPRunDB(RunDBInterface):
2763
3054
  provider: Union[
2764
3055
  str, mlrun.common.schemas.SecretProviderName
2765
3056
  ] = mlrun.common.schemas.SecretProviderName.kubernetes,
2766
- secrets: List[str] = None,
3057
+ secrets: list[str] = None,
2767
3058
  ):
2768
3059
  """Delete project-context secrets from Kubernetes.
2769
3060
 
@@ -2920,13 +3211,13 @@ class HTTPRunDB(RunDBInterface):
2920
3211
  project: str,
2921
3212
  model: Optional[str] = None,
2922
3213
  function: Optional[str] = None,
2923
- labels: List[str] = None,
3214
+ labels: list[str] = None,
2924
3215
  start: str = "now-1h",
2925
3216
  end: str = "now",
2926
- metrics: Optional[List[str]] = None,
3217
+ metrics: Optional[list[str]] = None,
2927
3218
  top_level: bool = False,
2928
- uids: Optional[List[str]] = None,
2929
- ) -> List[mlrun.model_monitoring.model_endpoint.ModelEndpoint]:
3219
+ uids: Optional[list[str]] = None,
3220
+ ) -> list[mlrun.model_monitoring.model_endpoint.ModelEndpoint]:
2930
3221
  """
2931
3222
  Returns a list of `ModelEndpoint` objects. Each `ModelEndpoint` object represents the current state of a
2932
3223
  model endpoint. This functions supports filtering by the following parameters:
@@ -2947,14 +3238,12 @@ class HTTPRunDB(RunDBInterface):
2947
3238
  :param labels: A list of labels to filter by. Label filters work by either filtering a specific value of a
2948
3239
  label (i.e. list("key=value")) or by looking for the existence of a given key (i.e. "key")
2949
3240
  :param metrics: A list of metrics to return for each endpoint, read more in 'TimeMetric'
2950
- :param start: The start time of the metrics. Can be represented by a string containing an RFC 3339
2951
- time, a Unix timestamp in milliseconds, a relative time (`'now'` or
2952
- `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` =
2953
- days), or 0 for the earliest time.
2954
- :param end: The end time of the metrics. Can be represented by a string containing an RFC 3339
2955
- time, a Unix timestamp in milliseconds, a relative time (`'now'` or
2956
- `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` =
2957
- days), or 0 for the earliest time.
3241
+ :param start: The start time of the metrics. Can be represented by a string containing an RFC 3339 time, a
3242
+ Unix timestamp in milliseconds, a relative time (`'now'` or `'now-[0-9]+[mhd]'`, where
3243
+ `m` = minutes, `h` = hours, `'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
3244
+ :param end: The end time of the metrics. Can be represented by a string containing an RFC 3339 time, a
3245
+ Unix timestamp in milliseconds, a relative time (`'now'` or `'now-[0-9]+[mhd]'`, where
3246
+ `m` = minutes, `h` = hours, `'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
2958
3247
  :param top_level: if true will return only routers and endpoint that are NOT children of any router
2959
3248
  :param uids: if passed will return a list `ModelEndpoint` object with uid in uids
2960
3249
  """
@@ -2994,7 +3283,7 @@ class HTTPRunDB(RunDBInterface):
2994
3283
  endpoint_id: str,
2995
3284
  start: Optional[str] = None,
2996
3285
  end: Optional[str] = None,
2997
- metrics: Optional[List[str]] = None,
3286
+ metrics: Optional[list[str]] = None,
2998
3287
  feature_analysis: bool = False,
2999
3288
  ) -> mlrun.model_monitoring.model_endpoint.ModelEndpoint:
3000
3289
  """
@@ -3003,13 +3292,13 @@ class HTTPRunDB(RunDBInterface):
3003
3292
  :param project: The name of the project
3004
3293
  :param endpoint_id: The unique id of the model endpoint.
3005
3294
  :param start: The start time of the metrics. Can be represented by a string containing an
3006
- RFC 3339 time, a Unix timestamp in milliseconds, a relative time (`'now'` or
3007
- `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` = days), or
3008
- 0 for the earliest time.
3295
+ RFC 3339 time, a Unix timestamp in milliseconds, a relative time
3296
+ (`'now'` or `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours,
3297
+ `'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
3009
3298
  :param end: The end time of the metrics. Can be represented by a string containing an
3010
- RFC 3339 time, a Unix timestamp in milliseconds, a relative time (`'now'` or
3011
- `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` = days), or
3012
- 0 for the earliest time.
3299
+ RFC 3339 time, a Unix timestamp in milliseconds, a relative time
3300
+ (`'now'` or `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours,
3301
+ `'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
3013
3302
  :param metrics: A list of metrics to return for the model endpoint. There are pre-defined
3014
3303
  metrics for model endpoints such as predictions_per_second and
3015
3304
  latency_avg_5m but also custom metrics defined by the user. Please note that
@@ -3018,7 +3307,7 @@ class HTTPRunDB(RunDBInterface):
3018
3307
  :param feature_analysis: When True, the base feature statistics and current feature statistics will
3019
3308
  be added to the output of the resulting object.
3020
3309
 
3021
- :return: A `ModelEndpoint` object.
3310
+ :returns: A `ModelEndpoint` object.
3022
3311
  """
3023
3312
 
3024
3313
  path = f"projects/{project}/model-endpoints/{endpoint_id}"
@@ -3079,65 +3368,210 @@ class HTTPRunDB(RunDBInterface):
3079
3368
  params=attributes,
3080
3369
  )
3081
3370
 
3082
- def deploy_monitoring_batch_job(
3371
+ def update_model_monitoring_controller(
3083
3372
  self,
3084
- project: str = "",
3085
- default_batch_image: str = "mlrun/mlrun",
3086
- with_schedule: bool = False,
3087
- ):
3373
+ project: str,
3374
+ base_period: int = 10,
3375
+ image: str = "mlrun/mlrun",
3376
+ ) -> None:
3088
3377
  """
3089
- Submit model monitoring batch job. By default, submit only the batch job as ML function without scheduling.
3090
- To submit a scheduled job as well, please set with_schedule = True.
3378
+ Redeploy model monitoring application controller function.
3091
3379
 
3092
- :param project: Project name.
3093
- :param default_batch_image: The default image of the model monitoring batch job. By default, the image
3094
- is mlrun/mlrun.
3095
- :param with_schedule: If true, submit the model monitoring scheduled job as well.
3380
+ :param project: Project name.
3381
+ :param base_period: The time period in minutes in which the model monitoring controller function
3382
+ triggers. By default, the base period is 10 minutes.
3383
+ :param image: The image of the model monitoring controller function.
3384
+ By default, the image is mlrun/mlrun.
3385
+ """
3386
+ self.api_call(
3387
+ method=mlrun.common.types.HTTPMethod.PATCH,
3388
+ path=f"projects/{project}/model-monitoring/model-monitoring-controller",
3389
+ params={
3390
+ "base_period": base_period,
3391
+ "image": image,
3392
+ },
3393
+ )
3096
3394
 
3395
+ def enable_model_monitoring(
3396
+ self,
3397
+ project: str,
3398
+ base_period: int = 10,
3399
+ image: str = "mlrun/mlrun",
3400
+ deploy_histogram_data_drift_app: bool = True,
3401
+ rebuild_images: bool = False,
3402
+ fetch_credentials_from_sys_config: bool = False,
3403
+ ) -> None:
3404
+ """
3405
+ Deploy model monitoring application controller, writer and stream functions.
3406
+ While the main goal of the controller function is to handle the monitoring processing and triggering
3407
+ applications, the goal of the model monitoring writer function is to write all the monitoring
3408
+ application results to the databases.
3409
+ The stream function goal is to monitor the log of the data stream. It is triggered when a new log entry
3410
+ is detected. It processes the new events into statistics that are then written to statistics databases.
3411
+
3412
+ :param project: Project name.
3413
+ :param base_period: The time period in minutes in which the model monitoring controller
3414
+ function triggers. By default, the base period is 10 minutes.
3415
+ :param image: The image of the model monitoring controller, writer & monitoring
3416
+ stream functions, which are real time nuclio functions.
3417
+ By default, the image is mlrun/mlrun.
3418
+ :param deploy_histogram_data_drift_app: If true, deploy the default histogram-based data drift application.
3419
+ :param rebuild_images: If true, force rebuild of model monitoring infrastructure images.
3420
+ :param fetch_credentials_from_sys_config: If true, fetch the credentials from the system configuration.
3097
3421
 
3098
- :returns: model monitoring batch job as a dictionary. You can easily convert the returned function into a
3099
- runtime object by calling ~mlrun.new_function.
3100
3422
  """
3423
+ self.api_call(
3424
+ method=mlrun.common.types.HTTPMethod.POST,
3425
+ path=f"projects/{project}/model-monitoring/enable-model-monitoring",
3426
+ params={
3427
+ "base_period": base_period,
3428
+ "image": image,
3429
+ "deploy_histogram_data_drift_app": deploy_histogram_data_drift_app,
3430
+ "rebuild_images": rebuild_images,
3431
+ "fetch_credentials_from_sys_config": fetch_credentials_from_sys_config,
3432
+ },
3433
+ )
3101
3434
 
3102
- params = {
3103
- "default_batch_image": default_batch_image,
3104
- "with_schedule": with_schedule,
3105
- }
3106
- path = f"projects/{project}/jobs/batch-monitoring"
3435
+ def disable_model_monitoring(
3436
+ self,
3437
+ project: str,
3438
+ delete_resources: bool = True,
3439
+ delete_stream_function: bool = False,
3440
+ delete_histogram_data_drift_app: bool = True,
3441
+ delete_user_applications: bool = False,
3442
+ user_application_list: list[str] = None,
3443
+ ) -> bool:
3444
+ """
3445
+ Disable model monitoring application controller, writer, stream, histogram data drift application
3446
+ and the user's applications functions, according to the given params.
3447
+
3448
+ :param project: Project name.
3449
+ :param delete_resources: If True, it would delete the model monitoring controller & writer
3450
+ functions. Default True
3451
+ :param delete_stream_function: If True, it would delete model monitoring stream function,
3452
+ need to use wisely because if you're deleting this function
3453
+ this can cause data loss in case you will want to
3454
+ enable the model monitoring capability to the project.
3455
+ Default False.
3456
+ :param delete_histogram_data_drift_app: If True, it would delete the default histogram-based data drift
3457
+ application. Default False.
3458
+ :param delete_user_applications: If True, it would delete the user's model monitoring
3459
+ application according to user_application_list, Default False.
3460
+ :param user_application_list: List of the user's model monitoring application to disable.
3461
+ Default all the applications.
3462
+ Note: you have to set delete_user_applications to True
3463
+ in order to delete the desired application.
3464
+
3465
+ :returns: True if the deletion was successful, False otherwise.
3466
+ """
3467
+ response = self.api_call(
3468
+ method=mlrun.common.types.HTTPMethod.DELETE,
3469
+ path=f"projects/{project}/model-monitoring/disable-model-monitoring",
3470
+ params={
3471
+ "delete_resources": delete_resources,
3472
+ "delete_stream_function": delete_stream_function,
3473
+ "delete_histogram_data_drift_app": delete_histogram_data_drift_app,
3474
+ "delete_user_applications": delete_user_applications,
3475
+ "user_application_list": user_application_list,
3476
+ },
3477
+ )
3478
+ deletion_failed = False
3479
+ if response.status_code == http.HTTPStatus.ACCEPTED:
3480
+ if delete_resources:
3481
+ logger.info(
3482
+ "Model Monitoring is being disabled",
3483
+ project_name=project,
3484
+ )
3485
+ if delete_user_applications:
3486
+ logger.info("User applications are being deleted", project_name=project)
3487
+ background_tasks = mlrun.common.schemas.BackgroundTaskList(
3488
+ **response.json()
3489
+ ).background_tasks
3490
+ for task in background_tasks:
3491
+ task = self._wait_for_background_task_to_reach_terminal_state(
3492
+ task.metadata.name, project=project
3493
+ )
3494
+ if (
3495
+ task.status.state
3496
+ == mlrun.common.schemas.BackgroundTaskState.succeeded
3497
+ ):
3498
+ continue
3499
+ elif (
3500
+ task.status.state == mlrun.common.schemas.BackgroundTaskState.failed
3501
+ ):
3502
+ deletion_failed = True
3503
+ return not deletion_failed
3504
+
3505
+ def delete_model_monitoring_function(
3506
+ self, project: str, functions: list[str]
3507
+ ) -> bool:
3508
+ """
3509
+ Delete a model monitoring application.
3107
3510
 
3108
- resp = self.api_call(method="POST", path=path, params=params)
3109
- return resp.json()["func"]
3511
+ :param functions: List of the model monitoring function to delete.
3512
+ :param project: Project name.
3110
3513
 
3111
- def create_model_monitoring_controller(
3112
- self,
3113
- project: str = "",
3114
- default_controller_image: str = "mlrun/mlrun",
3115
- base_period: int = 10,
3116
- ):
3514
+ :returns: True if the deletion was successful, False otherwise.
3117
3515
  """
3118
- Submit model monitoring application controller job along with deploying the model monitoring writer function.
3119
- While the main goal of the controller job is to handle the monitoring processing and triggering applications,
3120
- the goal of the model monitoring writer function is to write all the monitoring application results to the
3121
- databases. Note that the default scheduling policy of the controller job is to run every 10 min.
3516
+ response = self.api_call(
3517
+ method=mlrun.common.types.HTTPMethod.DELETE,
3518
+ path=f"projects/{project}/model-monitoring/functions",
3519
+ params={"functions": functions},
3520
+ )
3521
+ deletion_failed = False
3522
+ if response.status_code == http.HTTPStatus.ACCEPTED:
3523
+ logger.info("User applications are being deleted", project_name=project)
3524
+ background_tasks = mlrun.common.schemas.BackgroundTaskList(
3525
+ **response.json()
3526
+ ).background_tasks
3527
+ for task in background_tasks:
3528
+ task = self._wait_for_background_task_to_reach_terminal_state(
3529
+ task.metadata.name, project=project
3530
+ )
3531
+ if (
3532
+ task.status.state
3533
+ == mlrun.common.schemas.BackgroundTaskState.succeeded
3534
+ ):
3535
+ continue
3536
+ elif (
3537
+ task.status.state == mlrun.common.schemas.BackgroundTaskState.failed
3538
+ ):
3539
+ deletion_failed = True
3540
+ return not deletion_failed
3541
+
3542
+ def deploy_histogram_data_drift_app(
3543
+ self, project: str, image: str = "mlrun/mlrun"
3544
+ ) -> None:
3545
+ """
3546
+ Deploy the histogram data drift application.
3122
3547
 
3123
- :param project: Project name.
3124
- :param default_controller_image: The default image of the model monitoring controller job. Note that the writer
3125
- function, which is a real time nuclio functino, will be deployed with the same
3126
- image. By default, the image is mlrun/mlrun.
3127
- :param base_period: Minutes to determine the frequency in which the model monitoring controller job
3128
- is running. By default, the base period is 5 minutes.
3129
- :returns: model monitoring controller job as a dictionary. You can easily convert the returned function into a
3130
- runtime object by calling ~mlrun.new_function.
3548
+ :param project: Project name.
3549
+ :param image: The image on which the application will run.
3131
3550
  """
3551
+ self.api_call(
3552
+ method=mlrun.common.types.HTTPMethod.POST,
3553
+ path=f"projects/{project}/model-monitoring/deploy-histogram-data-drift-app",
3554
+ params={"image": image},
3555
+ )
3132
3556
 
3133
- params = {
3134
- "default_controller_image": default_controller_image,
3135
- "base_period": base_period,
3136
- }
3137
- path = f"projects/{project}/jobs/model-monitoring-controller"
3557
+ def set_model_monitoring_credentials(
3558
+ self,
3559
+ project: str,
3560
+ credentials: dict[str, str],
3561
+ replace_creds: bool,
3562
+ ) -> None:
3563
+ """
3564
+ Set the credentials for the model monitoring application.
3138
3565
 
3139
- resp = self.api_call(method="POST", path=path, params=params)
3140
- return resp.json()["func"]
3566
+ :param project: Project name.
3567
+ :param credentials: Credentials to set.
3568
+ :param replace_creds: If True, will override the existing credentials.
3569
+ """
3570
+ self.api_call(
3571
+ method=mlrun.common.types.HTTPMethod.POST,
3572
+ path=f"projects/{project}/model-monitoring/set-model-monitoring-credentials",
3573
+ params={**credentials, "replace_creds": replace_creds},
3574
+ )
3141
3575
 
3142
3576
  def create_hub_source(
3143
3577
  self, source: Union[dict, mlrun.common.schemas.IndexedHubSource]
@@ -3168,8 +3602,10 @@ class HTTPRunDB(RunDBInterface):
3168
3602
  metadata=mlrun.common.schemas.HubObjectMetadata(
3169
3603
  name="priv", description="a private source"
3170
3604
  ),
3171
- spec=mlrun.common.schemas.HubSourceSpec(path="/local/path/to/source", channel="development")
3172
- )
3605
+ spec=mlrun.common.schemas.HubSourceSpec(
3606
+ path="/local/path/to/source", channel="development"
3607
+ ),
3608
+ ),
3173
3609
  )
3174
3610
  db.create_hub_source(private_source)
3175
3611
 
@@ -3183,9 +3619,9 @@ class HTTPRunDB(RunDBInterface):
3183
3619
  spec=mlrun.common.schemas.HubSourceSpec(
3184
3620
  path="/local/path/to/source/2",
3185
3621
  channel="development",
3186
- credentials={...}
3187
- )
3188
- )
3622
+ credentials={...},
3623
+ ),
3624
+ ),
3189
3625
  )
3190
3626
  db.create_hub_source(another_source)
3191
3627
 
@@ -3227,7 +3663,7 @@ class HTTPRunDB(RunDBInterface):
3227
3663
  item_name: Optional[str] = None,
3228
3664
  tag: Optional[str] = None,
3229
3665
  version: Optional[str] = None,
3230
- ) -> List[mlrun.common.schemas.hub.IndexedHubSource]:
3666
+ ) -> list[mlrun.common.schemas.hub.IndexedHubSource]:
3231
3667
  """
3232
3668
  List hub sources in the MLRun DB.
3233
3669
 
@@ -3349,7 +3785,7 @@ class HTTPRunDB(RunDBInterface):
3349
3785
  :param version: Get a specific version of the item. Default is ``None``.
3350
3786
  :param tag: Get a specific version of the item identified by tag. Default is ``latest``.
3351
3787
 
3352
- :return: http response with the asset in the content attribute
3788
+ :returns: http response with the asset in the content attribute
3353
3789
  """
3354
3790
  path = f"hub/sources/{source_name}/items/{item_name}/assets/{asset_name}"
3355
3791
  params = {
@@ -3377,24 +3813,81 @@ class HTTPRunDB(RunDBInterface):
3377
3813
  body=dict_to_json(authorization_verification_input.dict()),
3378
3814
  )
3379
3815
 
3380
- def list_api_gateways(self, project=None):
3816
+ def list_api_gateways(self, project=None) -> mlrun.common.schemas.APIGatewaysOutput:
3381
3817
  """
3382
3818
  Returns a list of Nuclio api gateways
3383
- :param project: optional str parameter to filter by project, if not passed, default Nuclio's value is taken
3384
3819
 
3385
- :return: json with the list of Nuclio Api Gateways
3386
- (json example is here
3387
- https://github.com/nuclio/nuclio/blob/development/docs/reference/api/README.md#listing-all-api-gateways)
3820
+ :param project: optional str parameter to filter by project, if not passed, default project value is taken
3821
+
3822
+ :returns: :py:class:`~mlrun.common.schemas.APIGateways`.
3388
3823
  """
3389
3824
  project = project or config.default_project
3390
3825
  error = "list api gateways"
3391
- endpoint_path = f"projects/{project}/nuclio/api-gateways"
3392
- resp = self.api_call("GET", endpoint_path, error)
3393
- return resp.json()
3826
+ endpoint_path = f"projects/{project}/api-gateways"
3827
+ response = self.api_call("GET", endpoint_path, error)
3828
+ return mlrun.common.schemas.APIGatewaysOutput(**response.json())
3829
+
3830
+ def get_api_gateway(self, name, project=None) -> mlrun.common.schemas.APIGateway:
3831
+ """
3832
+ Returns an API gateway
3833
+
3834
+ :param name: API gateway name
3835
+ :param project: optional str parameter to filter by project, if not passed, default project value is taken
3836
+
3837
+ :returns: :py:class:`~mlrun.common.schemas.APIGateway`.
3838
+ """
3839
+ project = project or config.default_project
3840
+ error = "get api gateway"
3841
+ endpoint_path = f"projects/{project}/api-gateways/{name}"
3842
+ response = self.api_call("GET", endpoint_path, error)
3843
+ return mlrun.common.schemas.APIGateway(**response.json())
3844
+
3845
+ def delete_api_gateway(self, name, project=None):
3846
+ """
3847
+ Deletes an API gateway
3848
+
3849
+ :param name: API gateway name
3850
+ :param project: Project name
3851
+ """
3852
+ project = project or config.default_project
3853
+ error = "delete api gateway"
3854
+ endpoint_path = f"projects/{project}/api-gateways/{name}"
3855
+ self.api_call("DELETE", endpoint_path, error)
3856
+
3857
+ def store_api_gateway(
3858
+ self,
3859
+ api_gateway: Union[
3860
+ mlrun.common.schemas.APIGateway,
3861
+ mlrun.runtimes.nuclio.api_gateway.APIGateway,
3862
+ ],
3863
+ project: Optional[str] = None,
3864
+ ) -> mlrun.common.schemas.APIGateway:
3865
+ """
3866
+ Stores an API Gateway.
3867
+
3868
+ :param api_gateway: :py:class:`~mlrun.runtimes.nuclio.APIGateway`
3869
+ or :py:class:`~mlrun.common.schemas.APIGateway`: API Gateway entity.
3870
+ :param project: project name. Mandatory if api_gateway is mlrun.common.schemas.APIGateway.
3871
+
3872
+ :returns: :py:class:`~mlrun.common.schemas.APIGateway`.
3873
+ """
3874
+
3875
+ if isinstance(api_gateway, mlrun.runtimes.nuclio.api_gateway.APIGateway):
3876
+ api_gateway = api_gateway.to_scheme()
3877
+ endpoint_path = f"projects/{project}/api-gateways/{api_gateway.metadata.name}"
3878
+ error = "store api gateways"
3879
+ response = self.api_call(
3880
+ "PUT",
3881
+ endpoint_path,
3882
+ error,
3883
+ json=api_gateway.dict(exclude_none=True),
3884
+ )
3885
+ return mlrun.common.schemas.APIGateway(**response.json())
3394
3886
 
3395
3887
  def trigger_migrations(self) -> Optional[mlrun.common.schemas.BackgroundTask]:
3396
3888
  """Trigger migrations (will do nothing if no migrations are needed) and wait for them to finish if actually
3397
3889
  triggered
3890
+
3398
3891
  :returns: :py:class:`~mlrun.common.schemas.BackgroundTask`.
3399
3892
  """
3400
3893
  response = self.api_call(
@@ -3413,10 +3906,11 @@ class HTTPRunDB(RunDBInterface):
3413
3906
  self,
3414
3907
  project: str,
3415
3908
  run_uid: str,
3416
- notifications: typing.List[mlrun.model.Notification] = None,
3909
+ notifications: list[mlrun.model.Notification] = None,
3417
3910
  ):
3418
3911
  """
3419
3912
  Set notifications on a run. This will override any existing notifications on the run.
3913
+
3420
3914
  :param project: Project containing the run.
3421
3915
  :param run_uid: UID of the run.
3422
3916
  :param notifications: List of notifications to set on the run. Default is an empty list.
@@ -3438,10 +3932,11 @@ class HTTPRunDB(RunDBInterface):
3438
3932
  self,
3439
3933
  project: str,
3440
3934
  schedule_name: str,
3441
- notifications: typing.List[mlrun.model.Notification] = None,
3935
+ notifications: list[mlrun.model.Notification] = None,
3442
3936
  ):
3443
3937
  """
3444
3938
  Set notifications on a schedule. This will override any existing notifications on the schedule.
3939
+
3445
3940
  :param project: Project containing the schedule.
3446
3941
  :param schedule_name: Name of the schedule.
3447
3942
  :param notifications: List of notifications to set on the schedule. Default is an empty list.
@@ -3461,7 +3956,7 @@ class HTTPRunDB(RunDBInterface):
3461
3956
 
3462
3957
  def store_run_notifications(
3463
3958
  self,
3464
- notification_objects: typing.List[mlrun.model.Notification],
3959
+ notification_objects: list[mlrun.model.Notification],
3465
3960
  run_uid: str,
3466
3961
  project: str = None,
3467
3962
  mask_params: bool = True,
@@ -3473,6 +3968,16 @@ class HTTPRunDB(RunDBInterface):
3473
3968
  """
3474
3969
  pass
3475
3970
 
3971
+ def store_alert_notifications(
3972
+ self,
3973
+ session,
3974
+ notification_objects: list[mlrun.model.Notification],
3975
+ alert_id: str,
3976
+ project: str,
3977
+ mask_params: bool = True,
3978
+ ):
3979
+ pass
3980
+
3476
3981
  def submit_workflow(
3477
3982
  self,
3478
3983
  project: str,
@@ -3482,7 +3987,7 @@ class HTTPRunDB(RunDBInterface):
3482
3987
  mlrun.common.schemas.WorkflowSpec,
3483
3988
  dict,
3484
3989
  ],
3485
- arguments: Optional[Dict] = None,
3990
+ arguments: Optional[dict] = None,
3486
3991
  artifact_path: Optional[str] = None,
3487
3992
  source: Optional[str] = None,
3488
3993
  run_name: Optional[str] = None,
@@ -3575,20 +4080,21 @@ class HTTPRunDB(RunDBInterface):
3575
4080
  self,
3576
4081
  name: str,
3577
4082
  url: str,
3578
- secrets: Optional[Dict] = None,
4083
+ secrets: Optional[dict] = None,
3579
4084
  save_secrets: bool = True,
3580
4085
  ) -> str:
3581
4086
  """
3582
4087
  Loading a project remotely from the given source.
4088
+
3583
4089
  :param name: project name
3584
4090
  :param url: git or tar.gz or .zip sources archive path e.g.:
3585
- git://github.com/mlrun/demo-xgb-project.git
3586
- http://mysite/archived-project.zip
3587
- The git project should include the project yaml file.
4091
+ git://github.com/mlrun/demo-xgb-project.git
4092
+ http://mysite/archived-project.zip
4093
+ The git project should include the project yaml file.
3588
4094
  :param secrets: Secrets to store in project in order to load it from the provided url. For more
3589
- information see :py:func:`mlrun.load_project` function.
4095
+ information see :py:func:`mlrun.load_project` function.
3590
4096
  :param save_secrets: Whether to store secrets in the loaded project. Setting to False will cause waiting
3591
- for the process completion.
4097
+ for the process completion.
3592
4098
 
3593
4099
  :returns: The terminal state of load project process.
3594
4100
  """
@@ -3638,7 +4144,7 @@ class HTTPRunDB(RunDBInterface):
3638
4144
 
3639
4145
  def list_datastore_profiles(
3640
4146
  self, project: str
3641
- ) -> List[mlrun.common.schemas.DatastoreProfile]:
4147
+ ) -> list[mlrun.common.schemas.DatastoreProfile]:
3642
4148
  project = project or config.default_project
3643
4149
  _path = self._path_of("datastore-profiles", project)
3644
4150
 
@@ -3664,6 +4170,168 @@ class HTTPRunDB(RunDBInterface):
3664
4170
 
3665
4171
  self.api_call(method="PUT", path=_path, json=profile.dict())
3666
4172
 
4173
+ @staticmethod
4174
+ def warn_on_s3_and_ecr_permissions_conflict(func):
4175
+ is_s3_source = func.spec.build.source and func.spec.build.source.startswith(
4176
+ "s3://"
4177
+ )
4178
+ is_ecr_image = mlrun.utils.is_ecr_url(config.httpdb.builder.docker_registry)
4179
+ if not func.spec.build.load_source_on_run and is_s3_source and is_ecr_image:
4180
+ logger.warning(
4181
+ "Building a function image to ECR and loading an S3 source to the image may require conflicting access "
4182
+ "keys. Only the permissions granted to the platform's configured secret will take affect "
4183
+ "(see mlrun.mlconf.httpdb.builder.docker_registry_secret). "
4184
+ "In case the permissions are limited to ECR scope, you may use pull_at_runtime=True instead",
4185
+ source=func.spec.build.source,
4186
+ load_source_on_run=func.spec.build.load_source_on_run,
4187
+ default_docker_registry=config.httpdb.builder.docker_registry,
4188
+ )
4189
+
4190
+ def generate_event(
4191
+ self, name: str, event_data: Union[dict, mlrun.common.schemas.Event], project=""
4192
+ ):
4193
+ """
4194
+ Generate an event.
4195
+
4196
+ :param name: The name of the event.
4197
+ :param event_data: The data of the event.
4198
+ :param project: The project that the event belongs to.
4199
+ """
4200
+ if mlrun.mlconf.alerts.mode == mlrun.common.schemas.alert.AlertsModes.disabled:
4201
+ logger.warning("Alerts are disabled, event will not be generated")
4202
+
4203
+ project = project or config.default_project
4204
+ endpoint_path = f"projects/{project}/events/{name}"
4205
+ error_message = f"post event {project}/events/{name}"
4206
+ if isinstance(event_data, mlrun.common.schemas.Event):
4207
+ event_data = event_data.dict()
4208
+ self.api_call(
4209
+ "POST", endpoint_path, error_message, body=dict_to_json(event_data)
4210
+ )
4211
+
4212
+ def store_alert_config(
4213
+ self,
4214
+ alert_name: str,
4215
+ alert_data: Union[dict, AlertConfig],
4216
+ project="",
4217
+ ) -> AlertConfig:
4218
+ """
4219
+ Create/modify an alert.
4220
+
4221
+ :param alert_name: The name of the alert.
4222
+ :param alert_data: The data of the alert.
4223
+ :param project: The project that the alert belongs to.
4224
+ :returns: The created/modified alert.
4225
+ """
4226
+ if not alert_data:
4227
+ raise mlrun.errors.MLRunInvalidArgumentError("Alert data must be provided")
4228
+
4229
+ if mlrun.mlconf.alerts.mode == mlrun.common.schemas.alert.AlertsModes.disabled:
4230
+ logger.warning(
4231
+ "Alerts are disabled, alert will still be stored but will not be triggered"
4232
+ )
4233
+
4234
+ project = project or config.default_project
4235
+ endpoint_path = f"projects/{project}/alerts/{alert_name}"
4236
+ error_message = f"put alert {project}/alerts/{alert_name}"
4237
+ alert_instance = (
4238
+ alert_data
4239
+ if isinstance(alert_data, AlertConfig)
4240
+ else AlertConfig.from_dict(alert_data)
4241
+ )
4242
+ # Validation is necessary here because users can directly invoke this function
4243
+ # through `mlrun.get_run_db().store_alert_config()`.
4244
+ alert_instance.validate_required_fields()
4245
+
4246
+ alert_data = alert_instance.to_dict()
4247
+ body = _as_json(alert_data)
4248
+ response = self.api_call("PUT", endpoint_path, error_message, body=body)
4249
+ return AlertConfig.from_dict(response.json())
4250
+
4251
+ def get_alert_config(self, alert_name: str, project="") -> AlertConfig:
4252
+ """
4253
+ Retrieve an alert.
4254
+
4255
+ :param alert_name: The name of the alert to retrieve.
4256
+ :param project: The project that the alert belongs to.
4257
+
4258
+ :returns: The alert object.
4259
+ """
4260
+ project = project or config.default_project
4261
+ endpoint_path = f"projects/{project}/alerts/{alert_name}"
4262
+ error_message = f"get alert {project}/alerts/{alert_name}"
4263
+ response = self.api_call("GET", endpoint_path, error_message)
4264
+ return AlertConfig.from_dict(response.json())
4265
+
4266
+ def list_alerts_configs(self, project="") -> list[AlertConfig]:
4267
+ """
4268
+ Retrieve list of alerts of a project.
4269
+
4270
+ :param project: The project name.
4271
+
4272
+ :returns: All the alerts objects of the project.
4273
+ """
4274
+ project = project or config.default_project
4275
+ endpoint_path = f"projects/{project}/alerts"
4276
+ error_message = f"get alerts {project}/alerts"
4277
+ response = self.api_call("GET", endpoint_path, error_message).json()
4278
+ results = []
4279
+ for item in response:
4280
+ results.append(AlertConfig(**item))
4281
+ return results
4282
+
4283
+ def delete_alert_config(self, alert_name: str, project=""):
4284
+ """
4285
+ Delete an alert.
4286
+ :param alert_name: The name of the alert to delete.
4287
+ :param project: The project that the alert belongs to.
4288
+ """
4289
+ project = project or config.default_project
4290
+ endpoint_path = f"projects/{project}/alerts/{alert_name}"
4291
+ error_message = f"delete alert {project}/alerts/{alert_name}"
4292
+ self.api_call("DELETE", endpoint_path, error_message)
4293
+
4294
+ def reset_alert_config(self, alert_name: str, project=""):
4295
+ """
4296
+ Reset an alert.
4297
+
4298
+ :param alert_name: The name of the alert to reset.
4299
+ :param project: The project that the alert belongs to.
4300
+ """
4301
+ project = project or config.default_project
4302
+ endpoint_path = f"projects/{project}/alerts/{alert_name}/reset"
4303
+ error_message = f"post alert {project}/alerts/{alert_name}/reset"
4304
+ self.api_call("POST", endpoint_path, error_message)
4305
+
4306
+ def get_alert_template(
4307
+ self, template_name: str
4308
+ ) -> mlrun.common.schemas.AlertTemplate:
4309
+ """
4310
+ Retrieve a specific alert template.
4311
+
4312
+ :param template_name: The name of the template to retrieve.
4313
+
4314
+ :returns: The template object.
4315
+ """
4316
+ endpoint_path = f"alert-templates/{template_name}"
4317
+ error_message = f"get template alert-templates/{template_name}"
4318
+ response = self.api_call("GET", endpoint_path, error_message)
4319
+ return mlrun.common.schemas.AlertTemplate(**response.json())
4320
+
4321
+ def list_alert_templates(self) -> list[mlrun.common.schemas.AlertTemplate]:
4322
+ """
4323
+ Retrieve list of all alert templates.
4324
+
4325
+ :returns: All the alert template objects in the database.
4326
+ """
4327
+ endpoint_path = "alert-templates"
4328
+ error_message = "get templates /alert-templates"
4329
+ response = self.api_call("GET", endpoint_path, error_message).json()
4330
+ results = []
4331
+ for item in response:
4332
+ results.append(mlrun.common.schemas.AlertTemplate(**item))
4333
+ return results
4334
+
3667
4335
 
3668
4336
  def _as_json(obj):
3669
4337
  fn = getattr(obj, "to_json", None)