mlrun 1.7.0rc15__py3-none-any.whl → 1.7.0rc17__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 (77) hide show
  1. mlrun/__init__.py +10 -1
  2. mlrun/__main__.py +18 -4
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +144 -0
  5. mlrun/artifacts/__init__.py +7 -1
  6. mlrun/artifacts/base.py +28 -3
  7. mlrun/artifacts/dataset.py +8 -0
  8. mlrun/artifacts/manager.py +18 -0
  9. mlrun/artifacts/model.py +8 -1
  10. mlrun/artifacts/plots.py +13 -0
  11. mlrun/common/schemas/__init__.py +10 -2
  12. mlrun/common/schemas/alert.py +64 -5
  13. mlrun/common/schemas/api_gateway.py +4 -0
  14. mlrun/common/schemas/artifact.py +15 -0
  15. mlrun/common/schemas/auth.py +2 -0
  16. mlrun/common/schemas/model_monitoring/__init__.py +4 -1
  17. mlrun/common/schemas/model_monitoring/constants.py +17 -1
  18. mlrun/common/schemas/model_monitoring/model_endpoints.py +60 -1
  19. mlrun/common/schemas/project.py +5 -1
  20. mlrun/config.py +11 -4
  21. mlrun/datastore/datastore_profile.py +10 -7
  22. mlrun/db/base.py +24 -4
  23. mlrun/db/httpdb.py +97 -43
  24. mlrun/db/nopdb.py +25 -4
  25. mlrun/errors.py +5 -0
  26. mlrun/launcher/base.py +3 -2
  27. mlrun/lists.py +4 -0
  28. mlrun/model.py +15 -8
  29. mlrun/model_monitoring/__init__.py +1 -1
  30. mlrun/model_monitoring/applications/_application_steps.py +1 -2
  31. mlrun/model_monitoring/applications/context.py +1 -1
  32. mlrun/model_monitoring/applications/histogram_data_drift.py +64 -38
  33. mlrun/model_monitoring/db/__init__.py +2 -0
  34. mlrun/model_monitoring/db/stores/base/store.py +9 -36
  35. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +63 -110
  36. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +56 -202
  37. mlrun/model_monitoring/db/tsdb/__init__.py +71 -0
  38. mlrun/model_monitoring/db/tsdb/base.py +135 -0
  39. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  40. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  41. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +442 -0
  42. mlrun/model_monitoring/db/v3io_tsdb_reader.py +134 -0
  43. mlrun/model_monitoring/stream_processing.py +46 -210
  44. mlrun/model_monitoring/writer.py +50 -100
  45. mlrun/platforms/__init__.py +10 -9
  46. mlrun/platforms/iguazio.py +19 -200
  47. mlrun/projects/operations.py +11 -7
  48. mlrun/projects/pipelines.py +13 -76
  49. mlrun/projects/project.py +62 -17
  50. mlrun/render.py +9 -3
  51. mlrun/run.py +5 -38
  52. mlrun/runtimes/__init__.py +1 -0
  53. mlrun/runtimes/base.py +3 -3
  54. mlrun/runtimes/kubejob.py +2 -1
  55. mlrun/runtimes/nuclio/api_gateway.py +163 -77
  56. mlrun/runtimes/nuclio/application/application.py +160 -7
  57. mlrun/runtimes/nuclio/function.py +25 -45
  58. mlrun/runtimes/pod.py +16 -36
  59. mlrun/runtimes/remotesparkjob.py +1 -1
  60. mlrun/runtimes/sparkjob/spark3job.py +1 -1
  61. mlrun/runtimes/utils.py +0 -38
  62. mlrun/track/tracker.py +2 -1
  63. mlrun/utils/helpers.py +51 -31
  64. mlrun/utils/logger.py +11 -6
  65. mlrun/utils/notifications/notification/base.py +1 -1
  66. mlrun/utils/notifications/notification/slack.py +9 -4
  67. mlrun/utils/notifications/notification/webhook.py +1 -1
  68. mlrun/utils/notifications/notification_pusher.py +21 -14
  69. mlrun/utils/version/version.json +2 -2
  70. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/METADATA +4 -3
  71. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/RECORD +75 -69
  72. mlrun/kfpops.py +0 -860
  73. mlrun/platforms/other.py +0 -305
  74. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/LICENSE +0 -0
  75. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/WHEEL +0 -0
  76. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/entry_points.txt +0 -0
  77. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/top_level.txt +0 -0
@@ -12,13 +12,20 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  import pathlib
15
+ import typing
15
16
 
16
17
  import nuclio
17
18
 
19
+ import mlrun.common.schemas as schemas
18
20
  import mlrun.errors
19
- from mlrun.common.schemas import AuthInfo
21
+ from mlrun.common.runtimes.constants import NuclioIngressAddTemplatedIngressModes
20
22
  from mlrun.runtimes import RemoteRuntime
21
23
  from mlrun.runtimes.nuclio import min_nuclio_versions
24
+ from mlrun.runtimes.nuclio.api_gateway import (
25
+ APIGateway,
26
+ APIGatewayMetadata,
27
+ APIGatewaySpec,
28
+ )
22
29
  from mlrun.runtimes.nuclio.function import NuclioSpec, NuclioStatus
23
30
 
24
31
 
@@ -113,7 +120,10 @@ class ApplicationSpec(NuclioSpec):
113
120
  state_thresholds=state_thresholds,
114
121
  disable_default_http_trigger=disable_default_http_trigger,
115
122
  )
116
- self.internal_application_port = internal_application_port or 8080
123
+ self.internal_application_port = (
124
+ internal_application_port
125
+ or mlrun.mlconf.function.application.default_sidecar_internal_port
126
+ )
117
127
 
118
128
  @property
119
129
  def internal_application_port(self):
@@ -139,6 +149,9 @@ class ApplicationStatus(NuclioStatus):
139
149
  container_image=None,
140
150
  application_image=None,
141
151
  sidecar_name=None,
152
+ api_gateway_name=None,
153
+ api_gateway=None,
154
+ url=None,
142
155
  ):
143
156
  super().__init__(
144
157
  state=state,
@@ -151,6 +164,9 @@ class ApplicationStatus(NuclioStatus):
151
164
  )
152
165
  self.application_image = application_image or None
153
166
  self.sidecar_name = sidecar_name or None
167
+ self.api_gateway_name = api_gateway_name or None
168
+ self.api_gateway = api_gateway or None
169
+ self.url = url or None
154
170
 
155
171
 
156
172
  class ApplicationRuntime(RemoteRuntime):
@@ -176,6 +192,24 @@ class ApplicationRuntime(RemoteRuntime):
176
192
  def status(self, status):
177
193
  self._status = self._verify_dict(status, "status", ApplicationStatus)
178
194
 
195
+ @property
196
+ def api_gateway(self):
197
+ return self.status.api_gateway
198
+
199
+ @api_gateway.setter
200
+ def api_gateway(self, api_gateway: APIGateway):
201
+ self.status.api_gateway = api_gateway
202
+
203
+ @property
204
+ def url(self):
205
+ if not self.status.api_gateway:
206
+ self._sync_api_gateway()
207
+ return self.status.api_gateway.invoke_url
208
+
209
+ @url.setter
210
+ def url(self, url):
211
+ self.status.url = url
212
+
179
213
  def set_internal_application_port(self, port: int):
180
214
  self.spec.internal_application_port = port
181
215
 
@@ -220,7 +254,7 @@ class ApplicationRuntime(RemoteRuntime):
220
254
  project="",
221
255
  tag="",
222
256
  verbose=False,
223
- auth_info: AuthInfo = None,
257
+ auth_info: schemas.AuthInfo = None,
224
258
  builder_env: dict = None,
225
259
  force_build: bool = False,
226
260
  with_mlrun=None,
@@ -228,6 +262,10 @@ class ApplicationRuntime(RemoteRuntime):
228
262
  is_kfp=False,
229
263
  mlrun_version_specifier=None,
230
264
  show_on_failure: bool = False,
265
+ skip_access_key_auth: bool = False,
266
+ direct_port_access: bool = False,
267
+ authentication_mode: schemas.APIGatewayAuthenticationMode = None,
268
+ authentication_creds: tuple[str] = None,
231
269
  ):
232
270
  """
233
271
  Deploy function, builds the application image if required (self.requires_build()) or force_build is True,
@@ -244,6 +282,10 @@ class ApplicationRuntime(RemoteRuntime):
244
282
  :param is_kfp: Deploy as part of a kfp pipeline
245
283
  :param mlrun_version_specifier: Which mlrun package version to include (if not current)
246
284
  :param show_on_failure: Show logs only in case of build failure
285
+ :param skip_access_key_auth: Skip adding access key auth to the API Gateway
286
+ :param direct_port_access: Set True to allow direct port access to the application sidecar
287
+ :param authentication_mode: API Gateway authentication mode
288
+ :param authentication_creds: API Gateway authentication credentials as a tuple (username, password)
247
289
  :return: True if the function is ready (deployed)
248
290
  """
249
291
  if self.requires_build() or force_build:
@@ -261,6 +303,16 @@ class ApplicationRuntime(RemoteRuntime):
261
303
 
262
304
  self._ensure_reverse_proxy_configurations()
263
305
  self._configure_application_sidecar()
306
+
307
+ # we only allow accessing the application via the API Gateway
308
+ name_tag = tag or self.metadata.tag
309
+ self.status.api_gateway_name = (
310
+ f"{self.metadata.name}-{name_tag}" if name_tag else self.metadata.name
311
+ )
312
+ self.spec.add_templated_ingress_host_mode = (
313
+ NuclioIngressAddTemplatedIngressModes.never
314
+ )
315
+
264
316
  super().deploy(
265
317
  project,
266
318
  tag,
@@ -269,6 +321,14 @@ class ApplicationRuntime(RemoteRuntime):
269
321
  builder_env,
270
322
  )
271
323
 
324
+ ports = self.spec.internal_application_port if direct_port_access else []
325
+ self.create_api_gateway(
326
+ name=self.status.api_gateway_name,
327
+ ports=ports,
328
+ authentication_mode=authentication_mode,
329
+ authentication_creds=authentication_creds,
330
+ )
331
+
272
332
  def with_source_archive(
273
333
  self, source, workdir=None, pull_at_runtime=True, target_dir=None
274
334
  ):
@@ -290,6 +350,92 @@ class ApplicationRuntime(RemoteRuntime):
290
350
  target_dir=target_dir,
291
351
  )
292
352
 
353
+ @classmethod
354
+ def get_filename_and_handler(cls) -> (str, str):
355
+ reverse_proxy_file_path = pathlib.Path(__file__).parent / "reverse_proxy.go"
356
+ return str(reverse_proxy_file_path), "Handler"
357
+
358
+ def create_api_gateway(
359
+ self,
360
+ name: str = None,
361
+ path: str = None,
362
+ ports: list[int] = None,
363
+ authentication_mode: schemas.APIGatewayAuthenticationMode = None,
364
+ authentication_creds: tuple[str] = None,
365
+ ):
366
+ api_gateway = APIGateway(
367
+ APIGatewayMetadata(
368
+ name=name,
369
+ namespace=self.metadata.namespace,
370
+ labels=self.metadata.labels,
371
+ annotations=self.metadata.annotations,
372
+ ),
373
+ APIGatewaySpec(
374
+ functions=[self],
375
+ project=self.metadata.project,
376
+ path=path,
377
+ ports=mlrun.utils.helpers.as_list(ports) if ports else None,
378
+ ),
379
+ )
380
+
381
+ authentication_mode = (
382
+ authentication_mode
383
+ or mlrun.mlconf.function.application.default_authentication_mode
384
+ )
385
+ if authentication_mode == schemas.APIGatewayAuthenticationMode.access_key:
386
+ api_gateway.with_access_key_auth()
387
+ elif authentication_mode == schemas.APIGatewayAuthenticationMode.basic:
388
+ api_gateway.with_basic_auth(*authentication_creds)
389
+
390
+ db = mlrun.get_run_db()
391
+ api_gateway_scheme = db.store_api_gateway(
392
+ api_gateway=api_gateway.to_scheme(), project=self.metadata.project
393
+ )
394
+ if not self.status.api_gateway_name:
395
+ self.status.api_gateway_name = api_gateway_scheme.metadata.name
396
+ self.status.api_gateway = APIGateway.from_scheme(api_gateway_scheme)
397
+ self.status.api_gateway.wait_for_readiness()
398
+ self.url = self.status.api_gateway.invoke_url
399
+
400
+ def invoke(
401
+ self,
402
+ path: str,
403
+ body: typing.Union[str, bytes, dict] = None,
404
+ method: str = None,
405
+ headers: dict = None,
406
+ dashboard: str = "",
407
+ force_external_address: bool = False,
408
+ auth_info: schemas.AuthInfo = None,
409
+ mock: bool = None,
410
+ **http_client_kwargs,
411
+ ):
412
+ self._sync_api_gateway()
413
+ # If the API Gateway is not ready or not set, try to invoke the function directly (without the API Gateway)
414
+ if not self.status.api_gateway:
415
+ super().invoke(
416
+ path,
417
+ body,
418
+ method,
419
+ headers,
420
+ dashboard,
421
+ force_external_address,
422
+ auth_info,
423
+ mock,
424
+ **http_client_kwargs,
425
+ )
426
+
427
+ credentials = (auth_info.username, auth_info.password) if auth_info else None
428
+
429
+ if not method:
430
+ method = "POST" if body else "GET"
431
+ return self.status.api_gateway.invoke(
432
+ method=method,
433
+ headers=headers,
434
+ credentials=credentials,
435
+ path=path,
436
+ **http_client_kwargs,
437
+ )
438
+
293
439
  def _build_application_image(
294
440
  self,
295
441
  builder_env: dict = None,
@@ -355,7 +501,14 @@ class ApplicationRuntime(RemoteRuntime):
355
501
  self.set_env("SIDECAR_PORT", self.spec.internal_application_port)
356
502
  self.set_env("SIDECAR_HOST", "http://localhost")
357
503
 
358
- @classmethod
359
- def get_filename_and_handler(cls) -> (str, str):
360
- reverse_proxy_file_path = pathlib.Path(__file__).parent / "reverse_proxy.go"
361
- return str(reverse_proxy_file_path), "Handler"
504
+ def _sync_api_gateway(self):
505
+ if not self.status.api_gateway_name:
506
+ return
507
+
508
+ db = mlrun.get_run_db()
509
+ api_gateway_scheme = db.get_api_gateway(
510
+ name=self.status.api_gateway_name, project=self.metadata.project
511
+ )
512
+ self.status.api_gateway = APIGateway.from_scheme(api_gateway_scheme)
513
+ self.status.api_gateway.wait_for_readiness()
514
+ self.url = self.status.api_gateway.invoke_url
@@ -22,9 +22,11 @@ from time import sleep
22
22
  import nuclio
23
23
  import nuclio.utils
24
24
  import requests
25
- import semver
26
25
  from aiohttp.client import ClientSession
27
26
  from kubernetes import client
27
+ from mlrun_pipelines.common.mounts import VolumeMount
28
+ from mlrun_pipelines.common.ops import deploy_op
29
+ from mlrun_pipelines.mounts import mount_v3io, v3io_cred
28
30
  from nuclio.deploy import find_dashboard_url, get_deploy_status
29
31
  from nuclio.triggers import V3IOStreamTrigger
30
32
 
@@ -36,15 +38,11 @@ import mlrun.utils.helpers
36
38
  from mlrun.common.schemas import AuthInfo
37
39
  from mlrun.config import config as mlconf
38
40
  from mlrun.errors import err_to_str
39
- from mlrun.kfpops import deploy_op
40
41
  from mlrun.lists import RunList
41
42
  from mlrun.model import RunObject
42
43
  from mlrun.platforms.iguazio import (
43
- VolumeMount,
44
- mount_v3io,
45
44
  parse_path,
46
45
  split_path,
47
- v3io_cred,
48
46
  )
49
47
  from mlrun.runtimes.base import FunctionStatus, RunError
50
48
  from mlrun.runtimes.pod import KubeResource, KubeResourceSpec
@@ -56,33 +54,9 @@ def validate_nuclio_version_compatibility(*min_versions):
56
54
  """
57
55
  :param min_versions: Valid minimum version(s) required, assuming no 2 versions has equal major and minor.
58
56
  """
59
- parsed_min_versions = [
60
- semver.VersionInfo.parse(min_version) for min_version in min_versions
61
- ]
62
- try:
63
- parsed_current_version = semver.VersionInfo.parse(mlconf.nuclio_version)
64
- except ValueError:
65
- # only log when version is set but invalid
66
- if mlconf.nuclio_version:
67
- logger.warning(
68
- "Unable to parse nuclio version, assuming compatibility",
69
- nuclio_version=mlconf.nuclio_version,
70
- min_versions=min_versions,
71
- )
72
- return True
73
-
74
- parsed_min_versions.sort(reverse=True)
75
- for parsed_min_version in parsed_min_versions:
76
- if (
77
- parsed_current_version.major == parsed_min_version.major
78
- and parsed_current_version.minor == parsed_min_version.minor
79
- and parsed_current_version.patch < parsed_min_version.patch
80
- ):
81
- return False
82
-
83
- if parsed_current_version >= parsed_min_version:
84
- return True
85
- return False
57
+ return mlrun.utils.helpers.validate_component_version_compatibility(
58
+ "nuclio", *min_versions
59
+ )
86
60
 
87
61
 
88
62
  def min_nuclio_versions(*versions):
@@ -573,7 +547,6 @@ class RemoteRuntime(KubeResource):
573
547
  if tag:
574
548
  self.metadata.tag = tag
575
549
 
576
- save_record = False
577
550
  # Attempt auto-mounting, before sending to remote build
578
551
  self.try_auto_mount_based_on_config()
579
552
  self._fill_credentials()
@@ -591,15 +564,18 @@ class RemoteRuntime(KubeResource):
591
564
  # now, functions can be not exposed (using service type ClusterIP) and hence
592
565
  # for BC we first try to populate the external invocation url, and then
593
566
  # if not exists, take the internal invocation url
594
- if self.status.external_invocation_urls:
567
+ if (
568
+ self.status.external_invocation_urls
569
+ and self.status.external_invocation_urls[0] != ""
570
+ ):
595
571
  self.spec.command = f"http://{self.status.external_invocation_urls[0]}"
596
- save_record = True
597
- elif self.status.internal_invocation_urls:
572
+ elif (
573
+ self.status.internal_invocation_urls
574
+ and self.status.internal_invocation_urls[0] != ""
575
+ ):
598
576
  self.spec.command = f"http://{self.status.internal_invocation_urls[0]}"
599
- save_record = True
600
- elif self.status.address:
577
+ elif self.status.address and self.status.address != "":
601
578
  self.spec.command = f"http://{self.status.address}"
602
- save_record = True
603
579
 
604
580
  logger.info(
605
581
  "Successfully deployed function",
@@ -607,8 +583,7 @@ class RemoteRuntime(KubeResource):
607
583
  external_invocation_urls=self.status.external_invocation_urls,
608
584
  )
609
585
 
610
- if save_record:
611
- self.save(versioned=False)
586
+ self.save(versioned=False)
612
587
 
613
588
  return self.spec.command
614
589
 
@@ -992,19 +967,24 @@ class RemoteRuntime(KubeResource):
992
967
  sidecar["image"] = image
993
968
 
994
969
  ports = mlrun.utils.helpers.as_list(ports)
970
+ # according to RFC-6335, port name should be less than 15 characters,
971
+ # so we truncate it if needed and leave room for the index
972
+ port_name = name[:13].rstrip("-_") if len(name) > 13 else name
995
973
  sidecar["ports"] = [
996
974
  {
997
- "name": "http",
975
+ "name": f"{port_name}-{i}",
998
976
  "containerPort": port,
999
977
  "protocol": "TCP",
1000
978
  }
1001
- for port in ports
979
+ for i, port in enumerate(ports)
1002
980
  ]
1003
981
 
1004
- if command:
982
+ # if it is a redeploy, 'command' might be set with the previous invocation url.
983
+ # in this case, we don't want to use it as the sidecar command
984
+ if command and not command.startswith("http"):
1005
985
  sidecar["command"] = mlrun.utils.helpers.as_list(command)
1006
986
 
1007
- if args:
987
+ if args and sidecar["command"]:
1008
988
  sidecar["args"] = mlrun.utils.helpers.as_list(args)
1009
989
 
1010
990
  def _set_sidecar(self, name: str) -> dict:
mlrun/runtimes/pod.py CHANGED
@@ -20,8 +20,9 @@ import typing
20
20
  from enum import Enum
21
21
 
22
22
  import dotenv
23
- import kfp.dsl
24
23
  import kubernetes.client as k8s_client
24
+ import mlrun_pipelines.mounts
25
+ from mlrun_pipelines.mixins import KfpAdapterMixin
25
26
 
26
27
  import mlrun.errors
27
28
  import mlrun.utils.regex
@@ -41,7 +42,6 @@ from ..k8s_utils import (
41
42
  from ..utils import logger, update_in
42
43
  from .base import BaseRuntime, FunctionSpec, spec_fields
43
44
  from .utils import (
44
- apply_kfp,
45
45
  get_gpu_from_resource_requirement,
46
46
  get_item_name,
47
47
  set_named_item,
@@ -935,12 +935,12 @@ class AutoMountType(str, Enum):
935
935
  @classmethod
936
936
  def all_mount_modifiers(cls):
937
937
  return [
938
- mlrun.v3io_cred.__name__,
939
- mlrun.mount_v3io.__name__,
940
- mlrun.platforms.other.mount_pvc.__name__,
941
- mlrun.auto_mount.__name__,
942
- mlrun.platforms.mount_s3.__name__,
943
- mlrun.platforms.set_env_variables.__name__,
938
+ mlrun_pipelines.mounts.v3io_cred.__name__,
939
+ mlrun_pipelines.mounts.mount_v3io.__name__,
940
+ mlrun_pipelines.mounts.mount_pvc.__name__,
941
+ mlrun_pipelines.mounts.auto_mount.__name__,
942
+ mlrun_pipelines.mounts.mount_s3.__name__,
943
+ mlrun_pipelines.mounts.set_env_variables.__name__,
944
944
  ]
945
945
 
946
946
  @classmethod
@@ -957,27 +957,27 @@ class AutoMountType(str, Enum):
957
957
  def _get_auto_modifier():
958
958
  # If we're running on Iguazio - use v3io_cred
959
959
  if mlconf.igz_version != "":
960
- return mlrun.v3io_cred
960
+ return mlrun_pipelines.mounts.v3io_cred
961
961
  # Else, either pvc mount if it's configured or do nothing otherwise
962
962
  pvc_configured = (
963
963
  "MLRUN_PVC_MOUNT" in os.environ
964
964
  or "pvc_name" in mlconf.get_storage_auto_mount_params()
965
965
  )
966
- return mlrun.platforms.other.mount_pvc if pvc_configured else None
966
+ return mlrun_pipelines.mounts.mount_pvc if pvc_configured else None
967
967
 
968
968
  def get_modifier(self):
969
969
  return {
970
970
  AutoMountType.none: None,
971
- AutoMountType.v3io_credentials: mlrun.v3io_cred,
972
- AutoMountType.v3io_fuse: mlrun.mount_v3io,
973
- AutoMountType.pvc: mlrun.platforms.other.mount_pvc,
971
+ AutoMountType.v3io_credentials: mlrun_pipelines.mounts.v3io_cred,
972
+ AutoMountType.v3io_fuse: mlrun_pipelines.mounts.mount_v3io,
973
+ AutoMountType.pvc: mlrun_pipelines.mounts.mount_pvc,
974
974
  AutoMountType.auto: self._get_auto_modifier(),
975
- AutoMountType.s3: mlrun.platforms.mount_s3,
976
- AutoMountType.env: mlrun.platforms.set_env_variables,
975
+ AutoMountType.s3: mlrun_pipelines.mounts.mount_s3,
976
+ AutoMountType.env: mlrun_pipelines.mounts.set_env_variables,
977
977
  }[self]
978
978
 
979
979
 
980
- class KubeResource(BaseRuntime):
980
+ class KubeResource(BaseRuntime, KfpAdapterMixin):
981
981
  """
982
982
  A parent class for runtimes that generate k8s resources when executing.
983
983
  """
@@ -997,26 +997,6 @@ class KubeResource(BaseRuntime):
997
997
  def spec(self, spec):
998
998
  self._spec = self._verify_dict(spec, "spec", KubeResourceSpec)
999
999
 
1000
- def apply(self, modify):
1001
- """
1002
- Apply a modifier to the runtime which is used to change the runtimes k8s object's spec.
1003
- Modifiers can be either KFP modifiers or MLRun modifiers (which are compatible with KFP). All modifiers accept
1004
- a `kfp.dsl.ContainerOp` object, apply some changes on its spec and return it so modifiers can be chained
1005
- one after the other.
1006
-
1007
- :param modify: a modifier runnable object
1008
- :return: the runtime (self) after the modifications
1009
- """
1010
-
1011
- # Kubeflow pipeline have a hook to add the component to the DAG on ContainerOp init
1012
- # we remove the hook to suppress kubeflow op registration and return it after the apply()
1013
- old_op_handler = kfp.dsl._container_op._register_op_handler
1014
- kfp.dsl._container_op._register_op_handler = lambda x: self.metadata.name
1015
- cop = kfp.dsl.ContainerOp("name", "image")
1016
- kfp.dsl._container_op._register_op_handler = old_op_handler
1017
-
1018
- return apply_kfp(modify, cop, self)
1019
-
1020
1000
  def set_env_from_secret(self, name, secret=None, secret_key=None):
1021
1001
  """set pod environment var from secret"""
1022
1002
  secret_key = secret_key or name
@@ -15,11 +15,11 @@ import re
15
15
  from subprocess import run
16
16
 
17
17
  import kubernetes.client
18
+ from mlrun_pipelines.mounts import mount_v3io, mount_v3iod
18
19
 
19
20
  import mlrun.errors
20
21
  from mlrun.config import config
21
22
 
22
- from ..platforms.iguazio import mount_v3io, mount_v3iod
23
23
  from .kubejob import KubejobRuntime
24
24
  from .pod import KubeResourceSpec
25
25
 
@@ -14,6 +14,7 @@
14
14
  import typing
15
15
 
16
16
  import kubernetes.client
17
+ from mlrun_pipelines.mounts import mount_v3io, mount_v3iod
17
18
 
18
19
  import mlrun.common.schemas.function
19
20
  import mlrun.errors
@@ -22,7 +23,6 @@ from mlrun.config import config
22
23
 
23
24
  from ...execution import MLClientCtx
24
25
  from ...model import RunObject
25
- from ...platforms.iguazio import mount_v3io, mount_v3iod
26
26
  from ...utils import update_in, verify_field_regex
27
27
  from ..kubejob import KubejobRuntime
28
28
  from ..pod import KubeResourceSpec
mlrun/runtimes/utils.py CHANGED
@@ -20,7 +20,6 @@ from io import StringIO
20
20
  from sys import stderr
21
21
 
22
22
  import pandas as pd
23
- from kubernetes import client
24
23
 
25
24
  import mlrun
26
25
  import mlrun.common.constants
@@ -280,43 +279,6 @@ def get_item_name(item, attr="name"):
280
279
  return getattr(item, attr, None)
281
280
 
282
281
 
283
- def apply_kfp(modify, cop, runtime):
284
- modify(cop)
285
-
286
- # Have to do it here to avoid circular dependencies
287
- from .pod import AutoMountType
288
-
289
- if AutoMountType.is_auto_modifier(modify):
290
- runtime.spec.disable_auto_mount = True
291
-
292
- api = client.ApiClient()
293
- for k, v in cop.pod_labels.items():
294
- runtime.metadata.labels[k] = v
295
- for k, v in cop.pod_annotations.items():
296
- runtime.metadata.annotations[k] = v
297
- if cop.container.env:
298
- env_names = [
299
- e.name if hasattr(e, "name") else e["name"] for e in runtime.spec.env
300
- ]
301
- for e in api.sanitize_for_serialization(cop.container.env):
302
- name = e["name"]
303
- if name in env_names:
304
- runtime.spec.env[env_names.index(name)] = e
305
- else:
306
- runtime.spec.env.append(e)
307
- env_names.append(name)
308
- cop.container.env.clear()
309
-
310
- if cop.volumes and cop.container.volume_mounts:
311
- vols = api.sanitize_for_serialization(cop.volumes)
312
- mounts = api.sanitize_for_serialization(cop.container.volume_mounts)
313
- runtime.spec.update_vols_and_mounts(vols, mounts)
314
- cop.volumes.clear()
315
- cop.container.volume_mounts.clear()
316
-
317
- return runtime
318
-
319
-
320
282
  def verify_limits(
321
283
  resources_field_name,
322
284
  mem=None,
mlrun/track/tracker.py CHANGED
@@ -31,8 +31,9 @@ class Tracker(ABC):
31
31
  * Offline: Manually importing models and artifacts into an MLRun project using the `import_x` methods.
32
32
  """
33
33
 
34
+ @staticmethod
34
35
  @abstractmethod
35
- def is_enabled(self) -> bool:
36
+ def is_enabled() -> bool:
36
37
  """
37
38
  Checks if tracker is enabled.
38
39