mlrun 1.7.2rc3__py3-none-any.whl → 1.8.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 (275) hide show
  1. mlrun/__init__.py +26 -22
  2. mlrun/__main__.py +15 -16
  3. mlrun/alerts/alert.py +150 -15
  4. mlrun/api/schemas/__init__.py +1 -9
  5. mlrun/artifacts/__init__.py +2 -3
  6. mlrun/artifacts/base.py +62 -19
  7. mlrun/artifacts/dataset.py +17 -17
  8. mlrun/artifacts/document.py +454 -0
  9. mlrun/artifacts/manager.py +28 -18
  10. mlrun/artifacts/model.py +91 -59
  11. mlrun/artifacts/plots.py +2 -2
  12. mlrun/common/constants.py +8 -0
  13. mlrun/common/formatters/__init__.py +1 -0
  14. mlrun/common/formatters/artifact.py +1 -1
  15. mlrun/common/formatters/feature_set.py +2 -0
  16. mlrun/common/formatters/function.py +1 -0
  17. mlrun/{model_monitoring/db/stores/v3io_kv/__init__.py → common/formatters/model_endpoint.py} +17 -0
  18. mlrun/common/formatters/pipeline.py +1 -2
  19. mlrun/common/formatters/project.py +9 -0
  20. mlrun/common/model_monitoring/__init__.py +0 -5
  21. mlrun/common/model_monitoring/helpers.py +12 -62
  22. mlrun/common/runtimes/constants.py +25 -4
  23. mlrun/common/schemas/__init__.py +9 -5
  24. mlrun/common/schemas/alert.py +114 -19
  25. mlrun/common/schemas/api_gateway.py +3 -3
  26. mlrun/common/schemas/artifact.py +22 -9
  27. mlrun/common/schemas/auth.py +8 -4
  28. mlrun/common/schemas/background_task.py +7 -7
  29. mlrun/common/schemas/client_spec.py +4 -4
  30. mlrun/common/schemas/clusterization_spec.py +2 -2
  31. mlrun/common/schemas/common.py +53 -3
  32. mlrun/common/schemas/constants.py +15 -0
  33. mlrun/common/schemas/datastore_profile.py +1 -1
  34. mlrun/common/schemas/feature_store.py +9 -9
  35. mlrun/common/schemas/frontend_spec.py +4 -4
  36. mlrun/common/schemas/function.py +10 -10
  37. mlrun/common/schemas/hub.py +1 -1
  38. mlrun/common/schemas/k8s.py +3 -3
  39. mlrun/common/schemas/memory_reports.py +3 -3
  40. mlrun/common/schemas/model_monitoring/__init__.py +4 -8
  41. mlrun/common/schemas/model_monitoring/constants.py +127 -46
  42. mlrun/common/schemas/model_monitoring/grafana.py +18 -12
  43. mlrun/common/schemas/model_monitoring/model_endpoints.py +154 -160
  44. mlrun/common/schemas/notification.py +24 -3
  45. mlrun/common/schemas/object.py +1 -1
  46. mlrun/common/schemas/pagination.py +4 -4
  47. mlrun/common/schemas/partition.py +142 -0
  48. mlrun/common/schemas/pipeline.py +3 -3
  49. mlrun/common/schemas/project.py +26 -18
  50. mlrun/common/schemas/runs.py +3 -3
  51. mlrun/common/schemas/runtime_resource.py +5 -5
  52. mlrun/common/schemas/schedule.py +1 -1
  53. mlrun/common/schemas/secret.py +1 -1
  54. mlrun/{model_monitoring/db/stores/sqldb/__init__.py → common/schemas/serving.py} +10 -1
  55. mlrun/common/schemas/tag.py +3 -3
  56. mlrun/common/schemas/workflow.py +6 -5
  57. mlrun/common/types.py +1 -0
  58. mlrun/config.py +157 -89
  59. mlrun/data_types/__init__.py +5 -3
  60. mlrun/data_types/infer.py +13 -3
  61. mlrun/data_types/spark.py +2 -1
  62. mlrun/datastore/__init__.py +59 -18
  63. mlrun/datastore/alibaba_oss.py +4 -1
  64. mlrun/datastore/azure_blob.py +4 -1
  65. mlrun/datastore/base.py +19 -24
  66. mlrun/datastore/datastore.py +10 -4
  67. mlrun/datastore/datastore_profile.py +178 -45
  68. mlrun/datastore/dbfs_store.py +4 -1
  69. mlrun/datastore/filestore.py +4 -1
  70. mlrun/datastore/google_cloud_storage.py +4 -1
  71. mlrun/datastore/hdfs.py +4 -1
  72. mlrun/datastore/inmem.py +4 -1
  73. mlrun/datastore/redis.py +4 -1
  74. mlrun/datastore/s3.py +14 -3
  75. mlrun/datastore/sources.py +89 -92
  76. mlrun/datastore/store_resources.py +7 -4
  77. mlrun/datastore/storeytargets.py +51 -16
  78. mlrun/datastore/targets.py +38 -31
  79. mlrun/datastore/utils.py +87 -4
  80. mlrun/datastore/v3io.py +4 -1
  81. mlrun/datastore/vectorstore.py +291 -0
  82. mlrun/datastore/wasbfs/fs.py +13 -12
  83. mlrun/db/base.py +286 -100
  84. mlrun/db/httpdb.py +1562 -490
  85. mlrun/db/nopdb.py +250 -83
  86. mlrun/errors.py +6 -2
  87. mlrun/execution.py +194 -50
  88. mlrun/feature_store/__init__.py +2 -10
  89. mlrun/feature_store/api.py +20 -458
  90. mlrun/feature_store/common.py +9 -9
  91. mlrun/feature_store/feature_set.py +20 -18
  92. mlrun/feature_store/feature_vector.py +105 -479
  93. mlrun/feature_store/feature_vector_utils.py +466 -0
  94. mlrun/feature_store/retrieval/base.py +15 -11
  95. mlrun/feature_store/retrieval/job.py +2 -1
  96. mlrun/feature_store/retrieval/storey_merger.py +1 -1
  97. mlrun/feature_store/steps.py +3 -3
  98. mlrun/features.py +30 -13
  99. mlrun/frameworks/__init__.py +1 -2
  100. mlrun/frameworks/_common/__init__.py +1 -2
  101. mlrun/frameworks/_common/artifacts_library.py +2 -2
  102. mlrun/frameworks/_common/mlrun_interface.py +10 -6
  103. mlrun/frameworks/_common/model_handler.py +31 -31
  104. mlrun/frameworks/_common/producer.py +3 -1
  105. mlrun/frameworks/_dl_common/__init__.py +1 -2
  106. mlrun/frameworks/_dl_common/loggers/__init__.py +1 -2
  107. mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +4 -4
  108. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +3 -3
  109. mlrun/frameworks/_ml_common/__init__.py +1 -2
  110. mlrun/frameworks/_ml_common/loggers/__init__.py +1 -2
  111. mlrun/frameworks/_ml_common/model_handler.py +21 -21
  112. mlrun/frameworks/_ml_common/plans/__init__.py +1 -2
  113. mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +3 -1
  114. mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
  115. mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
  116. mlrun/frameworks/auto_mlrun/__init__.py +1 -2
  117. mlrun/frameworks/auto_mlrun/auto_mlrun.py +22 -15
  118. mlrun/frameworks/huggingface/__init__.py +1 -2
  119. mlrun/frameworks/huggingface/model_server.py +9 -9
  120. mlrun/frameworks/lgbm/__init__.py +47 -44
  121. mlrun/frameworks/lgbm/callbacks/__init__.py +1 -2
  122. mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -2
  123. mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -2
  124. mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -2
  125. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +5 -5
  126. mlrun/frameworks/lgbm/model_handler.py +15 -11
  127. mlrun/frameworks/lgbm/model_server.py +11 -7
  128. mlrun/frameworks/lgbm/utils.py +2 -2
  129. mlrun/frameworks/onnx/__init__.py +1 -2
  130. mlrun/frameworks/onnx/dataset.py +3 -3
  131. mlrun/frameworks/onnx/mlrun_interface.py +2 -2
  132. mlrun/frameworks/onnx/model_handler.py +7 -5
  133. mlrun/frameworks/onnx/model_server.py +8 -6
  134. mlrun/frameworks/parallel_coordinates.py +11 -11
  135. mlrun/frameworks/pytorch/__init__.py +22 -23
  136. mlrun/frameworks/pytorch/callbacks/__init__.py +1 -2
  137. mlrun/frameworks/pytorch/callbacks/callback.py +2 -1
  138. mlrun/frameworks/pytorch/callbacks/logging_callback.py +15 -8
  139. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +19 -12
  140. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +22 -15
  141. mlrun/frameworks/pytorch/callbacks_handler.py +36 -30
  142. mlrun/frameworks/pytorch/mlrun_interface.py +17 -17
  143. mlrun/frameworks/pytorch/model_handler.py +21 -17
  144. mlrun/frameworks/pytorch/model_server.py +13 -9
  145. mlrun/frameworks/sklearn/__init__.py +19 -18
  146. mlrun/frameworks/sklearn/estimator.py +2 -2
  147. mlrun/frameworks/sklearn/metric.py +3 -3
  148. mlrun/frameworks/sklearn/metrics_library.py +8 -6
  149. mlrun/frameworks/sklearn/mlrun_interface.py +3 -2
  150. mlrun/frameworks/sklearn/model_handler.py +4 -3
  151. mlrun/frameworks/tf_keras/__init__.py +11 -12
  152. mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -2
  153. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +17 -14
  154. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +15 -12
  155. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +21 -18
  156. mlrun/frameworks/tf_keras/model_handler.py +17 -13
  157. mlrun/frameworks/tf_keras/model_server.py +12 -8
  158. mlrun/frameworks/xgboost/__init__.py +19 -18
  159. mlrun/frameworks/xgboost/model_handler.py +13 -9
  160. mlrun/k8s_utils.py +2 -5
  161. mlrun/launcher/base.py +3 -4
  162. mlrun/launcher/client.py +2 -2
  163. mlrun/launcher/local.py +6 -2
  164. mlrun/launcher/remote.py +1 -1
  165. mlrun/lists.py +8 -4
  166. mlrun/model.py +132 -46
  167. mlrun/model_monitoring/__init__.py +3 -5
  168. mlrun/model_monitoring/api.py +113 -98
  169. mlrun/model_monitoring/applications/__init__.py +0 -5
  170. mlrun/model_monitoring/applications/_application_steps.py +81 -50
  171. mlrun/model_monitoring/applications/base.py +467 -14
  172. mlrun/model_monitoring/applications/context.py +212 -134
  173. mlrun/model_monitoring/{db/stores/base → applications/evidently}/__init__.py +6 -2
  174. mlrun/model_monitoring/applications/evidently/base.py +146 -0
  175. mlrun/model_monitoring/applications/histogram_data_drift.py +89 -56
  176. mlrun/model_monitoring/applications/results.py +67 -15
  177. mlrun/model_monitoring/controller.py +701 -315
  178. mlrun/model_monitoring/db/__init__.py +0 -2
  179. mlrun/model_monitoring/db/_schedules.py +242 -0
  180. mlrun/model_monitoring/db/_stats.py +189 -0
  181. mlrun/model_monitoring/db/tsdb/__init__.py +33 -22
  182. mlrun/model_monitoring/db/tsdb/base.py +243 -49
  183. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +76 -36
  184. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
  185. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py +213 -0
  186. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +534 -88
  187. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
  188. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +436 -106
  189. mlrun/model_monitoring/helpers.py +356 -114
  190. mlrun/model_monitoring/stream_processing.py +190 -345
  191. mlrun/model_monitoring/tracking_policy.py +11 -4
  192. mlrun/model_monitoring/writer.py +49 -90
  193. mlrun/package/__init__.py +3 -6
  194. mlrun/package/context_handler.py +2 -2
  195. mlrun/package/packager.py +12 -9
  196. mlrun/package/packagers/__init__.py +0 -2
  197. mlrun/package/packagers/default_packager.py +14 -11
  198. mlrun/package/packagers/numpy_packagers.py +16 -7
  199. mlrun/package/packagers/pandas_packagers.py +18 -18
  200. mlrun/package/packagers/python_standard_library_packagers.py +25 -11
  201. mlrun/package/packagers_manager.py +35 -32
  202. mlrun/package/utils/__init__.py +0 -3
  203. mlrun/package/utils/_pickler.py +6 -6
  204. mlrun/platforms/__init__.py +47 -16
  205. mlrun/platforms/iguazio.py +4 -1
  206. mlrun/projects/operations.py +30 -30
  207. mlrun/projects/pipelines.py +116 -47
  208. mlrun/projects/project.py +1292 -329
  209. mlrun/render.py +5 -9
  210. mlrun/run.py +57 -14
  211. mlrun/runtimes/__init__.py +1 -3
  212. mlrun/runtimes/base.py +30 -22
  213. mlrun/runtimes/daskjob.py +9 -9
  214. mlrun/runtimes/databricks_job/databricks_runtime.py +6 -5
  215. mlrun/runtimes/function_reference.py +5 -2
  216. mlrun/runtimes/generators.py +3 -2
  217. mlrun/runtimes/kubejob.py +6 -7
  218. mlrun/runtimes/mounts.py +574 -0
  219. mlrun/runtimes/mpijob/__init__.py +0 -2
  220. mlrun/runtimes/mpijob/abstract.py +7 -6
  221. mlrun/runtimes/nuclio/api_gateway.py +7 -7
  222. mlrun/runtimes/nuclio/application/application.py +11 -13
  223. mlrun/runtimes/nuclio/application/reverse_proxy.go +66 -64
  224. mlrun/runtimes/nuclio/function.py +127 -70
  225. mlrun/runtimes/nuclio/serving.py +105 -37
  226. mlrun/runtimes/pod.py +159 -54
  227. mlrun/runtimes/remotesparkjob.py +3 -2
  228. mlrun/runtimes/sparkjob/__init__.py +0 -2
  229. mlrun/runtimes/sparkjob/spark3job.py +22 -12
  230. mlrun/runtimes/utils.py +7 -6
  231. mlrun/secrets.py +2 -2
  232. mlrun/serving/__init__.py +8 -0
  233. mlrun/serving/merger.py +7 -5
  234. mlrun/serving/remote.py +35 -22
  235. mlrun/serving/routers.py +186 -240
  236. mlrun/serving/server.py +41 -10
  237. mlrun/serving/states.py +432 -118
  238. mlrun/serving/utils.py +13 -2
  239. mlrun/serving/v1_serving.py +3 -2
  240. mlrun/serving/v2_serving.py +161 -203
  241. mlrun/track/__init__.py +1 -1
  242. mlrun/track/tracker.py +2 -2
  243. mlrun/track/trackers/mlflow_tracker.py +6 -5
  244. mlrun/utils/async_http.py +35 -22
  245. mlrun/utils/clones.py +7 -4
  246. mlrun/utils/helpers.py +511 -58
  247. mlrun/utils/logger.py +119 -13
  248. mlrun/utils/notifications/notification/__init__.py +22 -19
  249. mlrun/utils/notifications/notification/base.py +39 -15
  250. mlrun/utils/notifications/notification/console.py +6 -6
  251. mlrun/utils/notifications/notification/git.py +11 -11
  252. mlrun/utils/notifications/notification/ipython.py +10 -9
  253. mlrun/utils/notifications/notification/mail.py +176 -0
  254. mlrun/utils/notifications/notification/slack.py +16 -8
  255. mlrun/utils/notifications/notification/webhook.py +24 -8
  256. mlrun/utils/notifications/notification_pusher.py +191 -200
  257. mlrun/utils/regex.py +12 -2
  258. mlrun/utils/version/version.json +2 -2
  259. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info}/METADATA +81 -54
  260. mlrun-1.8.0.dist-info/RECORD +351 -0
  261. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info}/WHEEL +1 -1
  262. mlrun/model_monitoring/applications/evidently_base.py +0 -137
  263. mlrun/model_monitoring/db/stores/__init__.py +0 -136
  264. mlrun/model_monitoring/db/stores/base/store.py +0 -213
  265. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -71
  266. mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -190
  267. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -103
  268. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -40
  269. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -659
  270. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -726
  271. mlrun/model_monitoring/model_endpoint.py +0 -118
  272. mlrun-1.7.2rc3.dist-info/RECORD +0 -351
  273. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info}/entry_points.txt +0 -0
  274. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info/licenses}/LICENSE +0 -0
  275. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info}/top_level.txt +0 -0
mlrun/runtimes/pod.py CHANGED
@@ -17,14 +17,16 @@ import os
17
17
  import re
18
18
  import time
19
19
  import typing
20
+ from collections.abc import Iterable
20
21
  from enum import Enum
21
22
 
22
23
  import dotenv
23
24
  import kubernetes.client as k8s_client
24
- import mlrun_pipelines.mounts
25
- from mlrun_pipelines.mixins import KfpAdapterMixin
25
+ from kubernetes.client import V1Volume, V1VolumeMount
26
26
 
27
+ import mlrun.common.constants
27
28
  import mlrun.errors
29
+ import mlrun.runtimes.mounts
28
30
  import mlrun.utils.regex
29
31
  from mlrun.common.schemas import (
30
32
  NodeSelectorOperator,
@@ -212,9 +214,7 @@ class KubeResourceSpec(FunctionSpec):
212
214
  # default service account is set in mlrun.utils.process_function_service_account
213
215
  # due to project specific defaults
214
216
  self.service_account = service_account
215
- self.image_pull_secret = (
216
- image_pull_secret or mlrun.mlconf.function.spec.image_pull_secret.default
217
- )
217
+ self.image_pull_secret = image_pull_secret
218
218
  self.node_name = node_name
219
219
  self.node_selector = node_selector or {}
220
220
  self._affinity = affinity
@@ -309,7 +309,7 @@ class KubeResourceSpec(FunctionSpec):
309
309
  return self._termination_grace_period_seconds
310
310
 
311
311
  def _serialize_field(
312
- self, struct: dict, field_name: str = None, strip: bool = False
312
+ self, struct: dict, field_name: typing.Optional[str] = None, strip: bool = False
313
313
  ) -> typing.Any:
314
314
  """
315
315
  Serialize a field to a dict, list, or primitive type.
@@ -321,7 +321,7 @@ class KubeResourceSpec(FunctionSpec):
321
321
  return super()._serialize_field(struct, field_name, strip)
322
322
 
323
323
  def _enrich_field(
324
- self, struct: dict, field_name: str = None, strip: bool = False
324
+ self, struct: dict, field_name: typing.Optional[str] = None, strip: bool = False
325
325
  ) -> typing.Any:
326
326
  k8s_api = k8s_client.ApiClient()
327
327
  if strip:
@@ -366,6 +366,35 @@ class KubeResourceSpec(FunctionSpec):
366
366
  + f"service accounts {allowed_service_accounts}"
367
367
  )
368
368
 
369
+ def with_volumes(
370
+ self,
371
+ volumes: typing.Union[list[dict], dict, V1Volume],
372
+ ) -> "KubeResourceSpec":
373
+ """Add volumes to the volumes dictionary, only used as part of the mlrun_pipelines mount functions."""
374
+ if isinstance(volumes, dict):
375
+ set_named_item(self._volumes, volumes)
376
+ elif isinstance(volumes, Iterable):
377
+ for volume in volumes:
378
+ set_named_item(self._volumes, volume)
379
+ else:
380
+ set_named_item(self._volumes, volumes)
381
+ return self
382
+
383
+ def with_volume_mounts(
384
+ self,
385
+ volume_mounts: typing.Union[list[dict], dict, V1VolumeMount],
386
+ ) -> "KubeResourceSpec":
387
+ """Add volume mounts to the volume mounts dictionary,
388
+ only used as part of the mlrun_pipelines mount functions."""
389
+ if isinstance(volume_mounts, dict):
390
+ self._set_volume_mount(volume_mounts)
391
+ elif isinstance(volume_mounts, Iterable):
392
+ for volume_mount in volume_mounts:
393
+ self._set_volume_mount(volume_mount)
394
+ else:
395
+ self._set_volume_mount(volume_mounts)
396
+ return self
397
+
369
398
  def _set_volume_mount(
370
399
  self, volume_mount, volume_mounts_field_name="_volume_mounts"
371
400
  ):
@@ -380,9 +409,9 @@ class KubeResourceSpec(FunctionSpec):
380
409
  def _verify_and_set_limits(
381
410
  self,
382
411
  resources_field_name,
383
- mem: str = None,
384
- cpu: str = None,
385
- gpus: int = None,
412
+ mem: typing.Optional[str] = None,
413
+ cpu: typing.Optional[str] = None,
414
+ gpus: typing.Optional[int] = None,
386
415
  gpu_type: str = "nvidia.com/gpu",
387
416
  patch: bool = False,
388
417
  ):
@@ -430,8 +459,8 @@ class KubeResourceSpec(FunctionSpec):
430
459
  def _verify_and_set_requests(
431
460
  self,
432
461
  resources_field_name,
433
- mem: str = None,
434
- cpu: str = None,
462
+ mem: typing.Optional[str] = None,
463
+ cpu: typing.Optional[str] = None,
435
464
  patch: bool = False,
436
465
  ):
437
466
  resources = verify_requests(resources_field_name, mem=mem, cpu=cpu)
@@ -456,9 +485,9 @@ class KubeResourceSpec(FunctionSpec):
456
485
 
457
486
  def with_limits(
458
487
  self,
459
- mem: str = None,
460
- cpu: str = None,
461
- gpus: int = None,
488
+ mem: typing.Optional[str] = None,
489
+ cpu: typing.Optional[str] = None,
490
+ gpus: typing.Optional[int] = None,
462
491
  gpu_type: str = "nvidia.com/gpu",
463
492
  patch: bool = False,
464
493
  ):
@@ -474,7 +503,12 @@ class KubeResourceSpec(FunctionSpec):
474
503
  """
475
504
  self._verify_and_set_limits("resources", mem, cpu, gpus, gpu_type, patch=patch)
476
505
 
477
- def with_requests(self, mem: str = None, cpu: str = None, patch: bool = False):
506
+ def with_requests(
507
+ self,
508
+ mem: typing.Optional[str] = None,
509
+ cpu: typing.Optional[str] = None,
510
+ patch: bool = False,
511
+ ):
478
512
  """
479
513
  Set requested (desired) pod cpu/memory resources
480
514
 
@@ -936,12 +970,12 @@ class AutoMountType(str, Enum):
936
970
  @classmethod
937
971
  def all_mount_modifiers(cls):
938
972
  return [
939
- mlrun_pipelines.mounts.v3io_cred.__name__,
940
- mlrun_pipelines.mounts.mount_v3io.__name__,
941
- mlrun_pipelines.mounts.mount_pvc.__name__,
942
- mlrun_pipelines.mounts.auto_mount.__name__,
943
- mlrun_pipelines.mounts.mount_s3.__name__,
944
- mlrun_pipelines.mounts.set_env_variables.__name__,
973
+ mlrun.runtimes.mounts.v3io_cred.__name__,
974
+ mlrun.runtimes.mounts.mount_v3io.__name__,
975
+ mlrun.runtimes.mounts.mount_pvc.__name__,
976
+ mlrun.runtimes.mounts.auto_mount.__name__,
977
+ mlrun.runtimes.mounts.mount_s3.__name__,
978
+ mlrun.runtimes.mounts.set_env_variables.__name__,
945
979
  ]
946
980
 
947
981
  @classmethod
@@ -958,27 +992,27 @@ class AutoMountType(str, Enum):
958
992
  def _get_auto_modifier():
959
993
  # If we're running on Iguazio - use v3io_cred
960
994
  if mlconf.igz_version != "":
961
- return mlrun_pipelines.mounts.v3io_cred
995
+ return mlrun.runtimes.mounts.v3io_cred
962
996
  # Else, either pvc mount if it's configured or do nothing otherwise
963
997
  pvc_configured = (
964
998
  "MLRUN_PVC_MOUNT" in os.environ
965
999
  or "pvc_name" in mlconf.get_storage_auto_mount_params()
966
1000
  )
967
- return mlrun_pipelines.mounts.mount_pvc if pvc_configured else None
1001
+ return mlrun.runtimes.mounts.mount_pvc if pvc_configured else None
968
1002
 
969
1003
  def get_modifier(self):
970
1004
  return {
971
1005
  AutoMountType.none: None,
972
- AutoMountType.v3io_credentials: mlrun_pipelines.mounts.v3io_cred,
973
- AutoMountType.v3io_fuse: mlrun_pipelines.mounts.mount_v3io,
974
- AutoMountType.pvc: mlrun_pipelines.mounts.mount_pvc,
1006
+ AutoMountType.v3io_credentials: mlrun.runtimes.mounts.v3io_cred,
1007
+ AutoMountType.v3io_fuse: mlrun.runtimes.mounts.mount_v3io,
1008
+ AutoMountType.pvc: mlrun.runtimes.mounts.mount_pvc,
975
1009
  AutoMountType.auto: self._get_auto_modifier(),
976
- AutoMountType.s3: mlrun_pipelines.mounts.mount_s3,
977
- AutoMountType.env: mlrun_pipelines.mounts.set_env_variables,
1010
+ AutoMountType.s3: mlrun.runtimes.mounts.mount_s3,
1011
+ AutoMountType.env: mlrun.runtimes.mounts.set_env_variables,
978
1012
  }[self]
979
1013
 
980
1014
 
981
- class KubeResource(BaseRuntime, KfpAdapterMixin):
1015
+ class KubeResource(BaseRuntime):
982
1016
  """
983
1017
  A parent class for runtimes that generate k8s resources when executing.
984
1018
  """
@@ -1020,7 +1054,8 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1020
1054
 
1021
1055
  def get_env(self, name, default=None):
1022
1056
  """Get the pod environment variable for the given name, if not found return the default
1023
- If it's a scalar value, will return it, if the value is from source, return the k8s struct (V1EnvVarSource)"""
1057
+ If it's a scalar value, will return it, if the value is from source, return the k8s struct (V1EnvVarSource)
1058
+ """
1024
1059
  for env_var in self.spec.env:
1025
1060
  if get_item_name(env_var) == name:
1026
1061
  # valueFrom is a workaround for now, for some reason the envs aren't getting sanitized
@@ -1050,7 +1085,11 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1050
1085
  self.spec.env.append(new_var)
1051
1086
  return self
1052
1087
 
1053
- def set_envs(self, env_vars: dict = None, file_path: str = None):
1088
+ def set_envs(
1089
+ self,
1090
+ env_vars: typing.Optional[dict] = None,
1091
+ file_path: typing.Optional[str] = None,
1092
+ ):
1054
1093
  """set pod environment var from key/value dict or .env file
1055
1094
 
1056
1095
  :param env_vars: dict with env key/values
@@ -1070,11 +1109,16 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1070
1109
  else:
1071
1110
  raise mlrun.errors.MLRunNotFoundError(f"{file_path} does not exist")
1072
1111
  for name, value in env_vars.items():
1073
- self.set_env(name, value)
1112
+ if isinstance(value, dict) and "valueFrom" in value:
1113
+ self.set_env(name, value_from=value["valueFrom"])
1114
+ else:
1115
+ self.set_env(name, value)
1074
1116
  return self
1075
1117
 
1076
1118
  def set_image_pull_configuration(
1077
- self, image_pull_policy: str = None, image_pull_secret_name: str = None
1119
+ self,
1120
+ image_pull_policy: typing.Optional[str] = None,
1121
+ image_pull_secret_name: typing.Optional[str] = None,
1078
1122
  ):
1079
1123
  """
1080
1124
  Configure the image pull parameters for the runtime.
@@ -1123,9 +1167,9 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1123
1167
 
1124
1168
  def with_limits(
1125
1169
  self,
1126
- mem: str = None,
1127
- cpu: str = None,
1128
- gpus: int = None,
1170
+ mem: typing.Optional[str] = None,
1171
+ cpu: typing.Optional[str] = None,
1172
+ gpus: typing.Optional[int] = None,
1129
1173
  gpu_type: str = "nvidia.com/gpu",
1130
1174
  patch: bool = False,
1131
1175
  ):
@@ -1141,7 +1185,12 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1141
1185
  """
1142
1186
  self.spec.with_limits(mem, cpu, gpus, gpu_type, patch=patch)
1143
1187
 
1144
- def with_requests(self, mem: str = None, cpu: str = None, patch: bool = False):
1188
+ def with_requests(
1189
+ self,
1190
+ mem: typing.Optional[str] = None,
1191
+ cpu: typing.Optional[str] = None,
1192
+ patch: bool = False,
1193
+ ):
1145
1194
  """
1146
1195
  Set requested (desired) pod cpu/memory resources
1147
1196
 
@@ -1253,6 +1302,36 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1253
1302
  )
1254
1303
  self.spec.security_context = security_context
1255
1304
 
1305
+ def apply(
1306
+ self,
1307
+ modifier: typing.Callable[["KubeResource"], "KubeResource"],
1308
+ ) -> "KubeResource":
1309
+ """
1310
+ Apply a modifier to the runtime which is used to change the runtimes k8s object's spec.
1311
+ All modifiers accept Kube, apply some changes on its spec and return it so modifiers can be chained
1312
+ one after the other.
1313
+
1314
+ :param modifier: a modifier callable object
1315
+ :return: the runtime (self) after the modifications
1316
+ """
1317
+ modifier(self)
1318
+ if AutoMountType.is_auto_modifier(modifier):
1319
+ self.spec.disable_auto_mount = True
1320
+
1321
+ api_client = k8s_client.ApiClient()
1322
+ if self.spec.env:
1323
+ for index, env in enumerate(
1324
+ api_client.sanitize_for_serialization(self.spec.env)
1325
+ ):
1326
+ self.spec.env[index] = env
1327
+
1328
+ if self.spec.volumes and self.spec.volume_mounts:
1329
+ vols = api_client.sanitize_for_serialization(self.spec.volumes)
1330
+ mounts = api_client.sanitize_for_serialization(self.spec.volume_mounts)
1331
+ self.spec.update_vols_and_mounts(vols, mounts)
1332
+
1333
+ return self
1334
+
1256
1335
  def list_valid_priority_class_names(self):
1257
1336
  return mlconf.get_valid_function_priority_class_names()
1258
1337
 
@@ -1393,15 +1472,13 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1393
1472
  f"Started building image: {data.get('data', {}).get('spec', {}).get('build', {}).get('image')}"
1394
1473
  )
1395
1474
  if watch and not ready:
1396
- state = self._build_watch(
1475
+ self.status.state = self._build_watch(
1397
1476
  watch=watch,
1398
1477
  show_on_failure=show_on_failure,
1399
1478
  )
1400
- ready = state == "ready"
1401
- self.status.state = state
1402
-
1403
- if watch and not ready:
1404
- raise mlrun.errors.MLRunRuntimeError("Deploy failed")
1479
+ ready = self.status.state == "ready"
1480
+ if not ready:
1481
+ raise mlrun.errors.MLRunRuntimeError("Deploy failed")
1405
1482
  return ready
1406
1483
 
1407
1484
  def _build_watch(
@@ -1412,20 +1489,32 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1412
1489
  ):
1413
1490
  db = self._get_db()
1414
1491
  offset = 0
1492
+ events_offset = 0
1415
1493
  try:
1416
- text, _ = db.get_builder_status(self, 0, logs=logs)
1494
+ text, _, deploy_status_text_kind = db.get_builder_status(
1495
+ self,
1496
+ offset=0,
1497
+ logs=logs,
1498
+ events_offset=0,
1499
+ )
1417
1500
  except mlrun.db.RunDBError:
1418
- raise ValueError("function or build process not found")
1501
+ raise ValueError("Function or build process not found")
1419
1502
 
1420
- def print_log(text):
1421
- if text and (
1503
+ def print_log(_text):
1504
+ if _text and (
1422
1505
  not show_on_failure
1423
1506
  or self.status.state == mlrun.common.schemas.FunctionState.error
1424
1507
  ):
1425
- print(text, end="")
1508
+ print(_text, end="")
1426
1509
 
1427
1510
  print_log(text)
1428
- offset += len(text)
1511
+ if (
1512
+ deploy_status_text_kind
1513
+ == mlrun.common.constants.DeployStatusTextKind.events
1514
+ ):
1515
+ events_offset += len(text)
1516
+ else:
1517
+ offset += len(text)
1429
1518
  if watch:
1430
1519
  while self.status.state in [
1431
1520
  mlrun.common.schemas.FunctionState.pending,
@@ -1434,14 +1523,30 @@ class KubeResource(BaseRuntime, KfpAdapterMixin):
1434
1523
  time.sleep(2)
1435
1524
  if show_on_failure:
1436
1525
  text = ""
1437
- db.get_builder_status(self, 0, logs=False)
1526
+ db.get_builder_status(self, offset=0, logs=False, events_offset=0)
1438
1527
  if self.status.state == mlrun.common.schemas.FunctionState.error:
1439
1528
  # re-read the full log on failure
1440
- text, _ = db.get_builder_status(self, offset, logs=logs)
1529
+ text, _, deploy_status_text_kind = db.get_builder_status(
1530
+ self,
1531
+ offset=offset,
1532
+ logs=logs,
1533
+ events_offset=events_offset,
1534
+ )
1441
1535
  else:
1442
- text, _ = db.get_builder_status(self, offset, logs=logs)
1536
+ text, _, deploy_status_text_kind = db.get_builder_status(
1537
+ self,
1538
+ offset=offset,
1539
+ logs=logs,
1540
+ events_offset=events_offset,
1541
+ )
1443
1542
  print_log(text)
1444
- offset += len(text)
1543
+ if (
1544
+ deploy_status_text_kind
1545
+ == mlrun.common.constants.DeployStatusTextKind.events
1546
+ ):
1547
+ events_offset += len(text)
1548
+ else:
1549
+ offset += len(text)
1445
1550
 
1446
1551
  return self.status.state
1447
1552
 
@@ -13,12 +13,13 @@
13
13
  # limitations under the License.
14
14
  import re
15
15
  from subprocess import run
16
+ from typing import Optional
16
17
 
17
18
  import kubernetes.client
18
- from mlrun_pipelines.mounts import mount_v3io, mount_v3iod
19
19
 
20
20
  import mlrun.errors
21
21
  from mlrun.config import config
22
+ from mlrun.runtimes.mounts import mount_v3io, mount_v3iod
22
23
 
23
24
  from .kubejob import KubejobRuntime
24
25
  from .pod import KubeResourceSpec
@@ -179,7 +180,7 @@ class RemoteSparkRuntime(KubejobRuntime):
179
180
  skip_deployed=False,
180
181
  is_kfp=False,
181
182
  mlrun_version_specifier=None,
182
- builder_env: dict = None,
183
+ builder_env: Optional[dict] = None,
183
184
  show_on_failure: bool = False,
184
185
  force_build: bool = False,
185
186
  ):
@@ -12,6 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- # flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
16
-
17
15
  from .spark3job import Spark3Runtime
@@ -14,13 +14,13 @@
14
14
  import typing
15
15
 
16
16
  import kubernetes.client
17
- from mlrun_pipelines.mounts import mount_v3io, mount_v3iod
18
17
 
19
18
  import mlrun.common.schemas.function
20
19
  import mlrun.errors
21
20
  import mlrun.k8s_utils
22
21
  import mlrun.runtimes.pod
23
22
  from mlrun.config import config
23
+ from mlrun.runtimes.mounts import mount_v3io, mount_v3iod
24
24
 
25
25
  from ...execution import MLClientCtx
26
26
  from ...model import RunObject
@@ -405,8 +405,8 @@ class Spark3JobSpec(KubeResourceSpec):
405
405
  def _verify_and_set_requests(
406
406
  self,
407
407
  resources_field_name,
408
- mem: str = None,
409
- cpu: str = None,
408
+ mem: typing.Optional[str] = None,
409
+ cpu: typing.Optional[str] = None,
410
410
  patch: bool = False,
411
411
  ):
412
412
  # Spark operator uses JVM notation for memory, so we must verify it separately
@@ -774,7 +774,11 @@ class Spark3Runtime(KubejobRuntime):
774
774
  exporter_jar="/spark/jars/jmx_prometheus_javaagent-0.16.1.jar",
775
775
  )
776
776
 
777
- def with_cores(self, executor_cores: int = None, driver_cores: int = None):
777
+ def with_cores(
778
+ self,
779
+ executor_cores: typing.Optional[int] = None,
780
+ driver_cores: typing.Optional[int] = None,
781
+ ):
778
782
  """
779
783
  Allows to configure spark.executor.cores and spark.driver.cores parameters. The values must be integers
780
784
  greater than or equal to 1. If a parameter is not specified, it defaults to 1.
@@ -785,7 +789,7 @@ class Spark3Runtime(KubejobRuntime):
785
789
  Spark itself uses the spec.[executor|driver].cores parameter to set the parallelism of tasks and cores
786
790
  assigned to each task within the pod. This function sets the .cores parameters for the job executed.
787
791
 
788
- See https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/issues/581 for a discussion about those
792
+ See https://github.com/kubeflow/spark-operator/issues/581 for a discussion about those
789
793
  parameters and their meaning in Spark operator.
790
794
 
791
795
  :param executor_cores: Number of cores to use for executor (spark.executor.cores)
@@ -853,7 +857,7 @@ class Spark3Runtime(KubejobRuntime):
853
857
  skip_deployed=False,
854
858
  is_kfp=False,
855
859
  mlrun_version_specifier=None,
856
- builder_env: dict = None,
860
+ builder_env: typing.Optional[dict] = None,
857
861
  show_on_failure: bool = False,
858
862
  force_build: bool = False,
859
863
  ):
@@ -944,7 +948,10 @@ class Spark3Runtime(KubejobRuntime):
944
948
  )
945
949
 
946
950
  def with_executor_requests(
947
- self, mem: str = None, cpu: str = None, patch: bool = False
951
+ self,
952
+ mem: typing.Optional[str] = None,
953
+ cpu: typing.Optional[str] = None,
954
+ patch: bool = False,
948
955
  ):
949
956
  """
950
957
  set executor pod required cpu/memory/gpu resources
@@ -954,8 +961,8 @@ class Spark3Runtime(KubejobRuntime):
954
961
 
955
962
  def with_executor_limits(
956
963
  self,
957
- cpu: str = None,
958
- gpus: int = None,
964
+ cpu: typing.Optional[str] = None,
965
+ gpus: typing.Optional[int] = None,
959
966
  gpu_type: str = "nvidia.com/gpu",
960
967
  patch: bool = False,
961
968
  ):
@@ -970,7 +977,10 @@ class Spark3Runtime(KubejobRuntime):
970
977
  )
971
978
 
972
979
  def with_driver_requests(
973
- self, mem: str = None, cpu: str = None, patch: bool = False
980
+ self,
981
+ mem: typing.Optional[str] = None,
982
+ cpu: typing.Optional[str] = None,
983
+ patch: bool = False,
974
984
  ):
975
985
  """
976
986
  set driver pod required cpu/memory/gpu resources
@@ -980,8 +990,8 @@ class Spark3Runtime(KubejobRuntime):
980
990
 
981
991
  def with_driver_limits(
982
992
  self,
983
- cpu: str = None,
984
- gpus: int = None,
993
+ cpu: typing.Optional[str] = None,
994
+ gpus: typing.Optional[int] = None,
985
995
  gpu_type: str = "nvidia.com/gpu",
986
996
  patch: bool = False,
987
997
  ):
mlrun/runtimes/utils.py CHANGED
@@ -18,6 +18,7 @@ import os
18
18
  import re
19
19
  from io import StringIO
20
20
  from sys import stderr
21
+ from typing import Optional
21
22
 
22
23
  import pandas as pd
23
24
 
@@ -147,7 +148,7 @@ def add_code_metadata(path=""):
147
148
 
148
149
  def results_to_iter(results, runspec, execution):
149
150
  if not results:
150
- logger.error("got an empty results list in to_iter")
151
+ logger.error("Got an empty results list in to_iter")
151
152
  return
152
153
 
153
154
  iter = []
@@ -174,7 +175,7 @@ def results_to_iter(results, runspec, execution):
174
175
 
175
176
  if not iter:
176
177
  execution.set_state("completed", commit=True)
177
- logger.warning("warning!, zero iteration results")
178
+ logger.warning("Warning!, zero iteration results")
178
179
  return
179
180
  if hasattr(pd, "json_normalize"):
180
181
  df = pd.json_normalize(iter).sort_values("iter")
@@ -189,10 +190,10 @@ def results_to_iter(results, runspec, execution):
189
190
  item, id = selector(results, criteria)
190
191
  if runspec.spec.selector and not id:
191
192
  logger.warning(
192
- f"no best result selected, check selector ({criteria}) or results"
193
+ f"No best result selected, check selector ({criteria}) or results"
193
194
  )
194
195
  if id:
195
- logger.info(f"best iteration={id}, used criteria {criteria}")
196
+ logger.info(f"Best iteration={id}, used criteria {criteria}")
196
197
  task = results[item] if id and results else None
197
198
  execution.log_iteration_results(id, summary, task)
198
199
 
@@ -432,11 +433,11 @@ def enrich_function_from_dict(function, function_dict):
432
433
 
433
434
  def enrich_run_labels(
434
435
  labels: dict,
435
- labels_to_enrich: list[RunLabels] = None,
436
+ labels_to_enrich: Optional[list[RunLabels]] = None,
436
437
  ):
437
438
  labels_enrichment = {
438
439
  RunLabels.owner: os.environ.get("V3IO_USERNAME") or getpass.getuser(),
439
- # TODO: remove this in 1.9.0
440
+ # TODO: remove this in 1.10.0
440
441
  RunLabels.v3io_user: os.environ.get("V3IO_USERNAME"),
441
442
  }
442
443
  labels_to_enrich = labels_to_enrich or RunLabels.all()
mlrun/secrets.py CHANGED
@@ -134,7 +134,7 @@ class SecretsStore:
134
134
  def k8s_env_variable_name_for_secret(secret_name):
135
135
  from mlrun.config import config
136
136
 
137
- return config.secret_stores.kubernetes.env_variable_prefix + secret_name.upper()
137
+ return config.secret_stores.kubernetes.env_variable_prefix + secret_name
138
138
 
139
139
  def get_k8s_secrets(self):
140
140
  for source in self._hidden_sources:
@@ -151,7 +151,7 @@ def get_secret_or_env(
151
151
  secret_provider: Union[dict, SecretsStore, Callable, None] = None,
152
152
  default: Optional[str] = None,
153
153
  prefix: Optional[str] = None,
154
- ) -> str:
154
+ ) -> Optional[str]:
155
155
  """Retrieve value of a secret, either from a user-provided secret store, or from environment variables.
156
156
  The function will retrieve a secret value, attempting to find it according to the following order:
157
157
 
mlrun/serving/__init__.py CHANGED
@@ -23,6 +23,10 @@ __all__ = [
23
23
  "QueueStep",
24
24
  "ErrorStep",
25
25
  "MonitoringApplicationStep",
26
+ "ModelRunnerStep",
27
+ "ModelRunner",
28
+ "Model",
29
+ "ModelSelector",
26
30
  ]
27
31
 
28
32
  from .routers import ModelRouter, VotingEnsemble # noqa
@@ -33,6 +37,10 @@ from .states import (
33
37
  RouterStep,
34
38
  TaskStep,
35
39
  MonitoringApplicationStep,
40
+ ModelRunnerStep,
41
+ ModelRunner,
42
+ Model,
43
+ ModelSelector,
36
44
  ) # noqa
37
45
  from .v1_serving import MLModelServer, new_v1_model_server # noqa
38
46
  from .v2_serving import V2ModelServer # noqa
mlrun/serving/merger.py CHANGED
@@ -13,6 +13,8 @@
13
13
  # limitations under the License.
14
14
  #
15
15
 
16
+ from typing import Optional
17
+
16
18
  import storey
17
19
 
18
20
 
@@ -37,10 +39,10 @@ class CacheEntry:
37
39
  class Merge(storey.Flow):
38
40
  def __init__(
39
41
  self,
40
- full_event: bool = None,
41
- key_path: str = None,
42
- max_behind: int = None,
43
- expected_num_events: int = None,
42
+ full_event: Optional[bool] = None,
43
+ key_path: Optional[str] = None,
44
+ max_behind: Optional[int] = None,
45
+ expected_num_events: Optional[int] = None,
44
46
  **kwargs,
45
47
  ):
46
48
  """Merge multiple events based on event id or provided key path
@@ -72,7 +74,7 @@ class Merge(storey.Flow):
72
74
  self._queue_len = max_behind or 64 # default queue is 64 entries
73
75
  self._keys_queue = []
74
76
 
75
- def post_init(self, mode="sync"):
77
+ def post_init(self, mode="sync", **kwargs):
76
78
  # auto detect number of uplinks or use user specified value
77
79
  self._uplinks = self.expected_num_events or (
78
80
  len(self._graph_step.after) if self._graph_step else 0