mlrun 1.3.2rc1__py3-none-any.whl → 1.3.2rc2__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 (93) hide show
  1. mlrun/api/api/deps.py +14 -1
  2. mlrun/api/api/endpoints/frontend_spec.py +0 -2
  3. mlrun/api/api/endpoints/functions.py +15 -27
  4. mlrun/api/api/endpoints/grafana_proxy.py +435 -74
  5. mlrun/api/api/endpoints/healthz.py +5 -18
  6. mlrun/api/api/endpoints/model_endpoints.py +33 -37
  7. mlrun/api/api/utils.py +6 -13
  8. mlrun/api/crud/__init__.py +14 -16
  9. mlrun/api/crud/logs.py +5 -7
  10. mlrun/api/crud/model_monitoring/__init__.py +2 -2
  11. mlrun/api/crud/model_monitoring/model_endpoint_store.py +847 -0
  12. mlrun/api/crud/model_monitoring/model_endpoints.py +105 -328
  13. mlrun/api/crud/pipelines.py +2 -3
  14. mlrun/api/db/sqldb/models/models_mysql.py +52 -19
  15. mlrun/api/db/sqldb/models/models_sqlite.py +52 -19
  16. mlrun/api/db/sqldb/session.py +19 -26
  17. mlrun/api/schemas/__init__.py +2 -0
  18. mlrun/api/schemas/constants.py +0 -13
  19. mlrun/api/schemas/frontend_spec.py +0 -1
  20. mlrun/api/schemas/model_endpoints.py +38 -195
  21. mlrun/api/schemas/schedule.py +2 -2
  22. mlrun/api/utils/clients/log_collector.py +5 -0
  23. mlrun/builder.py +9 -41
  24. mlrun/config.py +1 -76
  25. mlrun/data_types/__init__.py +1 -6
  26. mlrun/data_types/data_types.py +1 -3
  27. mlrun/datastore/__init__.py +2 -9
  28. mlrun/datastore/sources.py +20 -25
  29. mlrun/datastore/store_resources.py +1 -1
  30. mlrun/datastore/targets.py +34 -67
  31. mlrun/datastore/utils.py +4 -26
  32. mlrun/db/base.py +2 -4
  33. mlrun/db/filedb.py +5 -13
  34. mlrun/db/httpdb.py +32 -64
  35. mlrun/db/sqldb.py +2 -4
  36. mlrun/errors.py +0 -5
  37. mlrun/execution.py +0 -2
  38. mlrun/feature_store/api.py +8 -24
  39. mlrun/feature_store/feature_set.py +6 -28
  40. mlrun/feature_store/feature_vector.py +0 -2
  41. mlrun/feature_store/ingestion.py +11 -8
  42. mlrun/feature_store/retrieval/base.py +43 -271
  43. mlrun/feature_store/retrieval/dask_merger.py +153 -55
  44. mlrun/feature_store/retrieval/job.py +3 -12
  45. mlrun/feature_store/retrieval/local_merger.py +130 -48
  46. mlrun/feature_store/retrieval/spark_merger.py +125 -126
  47. mlrun/features.py +2 -7
  48. mlrun/model_monitoring/constants.py +6 -48
  49. mlrun/model_monitoring/helpers.py +35 -118
  50. mlrun/model_monitoring/model_monitoring_batch.py +260 -293
  51. mlrun/model_monitoring/stream_processing_fs.py +253 -220
  52. mlrun/platforms/iguazio.py +0 -33
  53. mlrun/projects/project.py +72 -34
  54. mlrun/runtimes/base.py +0 -5
  55. mlrun/runtimes/daskjob.py +0 -2
  56. mlrun/runtimes/function.py +3 -29
  57. mlrun/runtimes/kubejob.py +15 -39
  58. mlrun/runtimes/local.py +45 -7
  59. mlrun/runtimes/mpijob/abstract.py +0 -2
  60. mlrun/runtimes/mpijob/v1.py +0 -2
  61. mlrun/runtimes/pod.py +0 -2
  62. mlrun/runtimes/remotesparkjob.py +0 -2
  63. mlrun/runtimes/serving.py +0 -6
  64. mlrun/runtimes/sparkjob/abstract.py +2 -39
  65. mlrun/runtimes/sparkjob/spark3job.py +0 -2
  66. mlrun/serving/__init__.py +1 -2
  67. mlrun/serving/routers.py +35 -35
  68. mlrun/serving/server.py +12 -22
  69. mlrun/serving/states.py +30 -162
  70. mlrun/serving/v2_serving.py +10 -13
  71. mlrun/utils/clones.py +1 -1
  72. mlrun/utils/model_monitoring.py +96 -122
  73. mlrun/utils/version/version.json +2 -2
  74. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/METADATA +27 -23
  75. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/RECORD +79 -92
  76. mlrun/api/crud/model_monitoring/grafana.py +0 -427
  77. mlrun/datastore/spark_udf.py +0 -40
  78. mlrun/model_monitoring/__init__.py +0 -44
  79. mlrun/model_monitoring/common.py +0 -112
  80. mlrun/model_monitoring/model_endpoint.py +0 -141
  81. mlrun/model_monitoring/stores/__init__.py +0 -106
  82. mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -448
  83. mlrun/model_monitoring/stores/model_endpoint_store.py +0 -147
  84. mlrun/model_monitoring/stores/models/__init__.py +0 -23
  85. mlrun/model_monitoring/stores/models/base.py +0 -18
  86. mlrun/model_monitoring/stores/models/mysql.py +0 -100
  87. mlrun/model_monitoring/stores/models/sqlite.py +0 -98
  88. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -375
  89. mlrun/utils/db.py +0 -52
  90. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/LICENSE +0 -0
  91. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/WHEEL +0 -0
  92. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/entry_points.txt +0 -0
  93. {mlrun-1.3.2rc1.dist-info → mlrun-1.3.2rc2.dist-info}/top_level.txt +0 -0
@@ -403,37 +403,6 @@ class OutputStream:
403
403
  )
404
404
 
405
405
 
406
- class HTTPOutputStream:
407
- """HTTP output source that usually used for CE mode and debugging process"""
408
-
409
- def __init__(self, stream_path: str):
410
- self._stream_path = stream_path
411
-
412
- def push(self, data):
413
- def dump_record(rec):
414
- if isinstance(rec, bytes):
415
- return rec
416
-
417
- if not isinstance(rec, str):
418
- rec = dict_to_json(rec)
419
-
420
- return rec.encode("UTF-8")
421
-
422
- if not isinstance(data, list):
423
- data = [data]
424
-
425
- for record in data:
426
-
427
- # Convert the new record to the required format
428
- serialized_record = dump_record(record)
429
- response = requests.post(self._stream_path, data=serialized_record)
430
- if not response:
431
- raise mlrun.errors.MLRunInvalidArgumentError(
432
- f"API call failed push a new record through {self._stream_path}"
433
- f"status {response.status_code}: {response.reason}"
434
- )
435
-
436
-
437
406
  class KafkaOutputStream:
438
407
  def __init__(
439
408
  self,
@@ -681,8 +650,6 @@ def parse_path(url, suffix="/"):
681
650
  )
682
651
  endpoint = f"{prefix}://{parsed_url.netloc}"
683
652
  else:
684
- # no netloc is mainly when using v3io (v3io:///) and expecting the url to be resolved automatically from env or
685
- # config
686
653
  endpoint = None
687
654
  return endpoint, parsed_url.path.strip("/") + suffix
688
655
 
mlrun/projects/project.py CHANGED
@@ -36,7 +36,6 @@ import yaml
36
36
  import mlrun.api.schemas
37
37
  import mlrun.db
38
38
  import mlrun.errors
39
- import mlrun.model_monitoring.constants as model_monitoring_constants
40
39
  import mlrun.utils.regex
41
40
  from mlrun.runtimes import RuntimeKinds
42
41
 
@@ -58,6 +57,7 @@ from ..utils import (
58
57
  )
59
58
  from ..utils.clones import clone_git, clone_tgz, clone_zip, get_repo_url
60
59
  from ..utils.helpers import ensure_git_branch, resolve_git_reference_from_source
60
+ from ..utils.model_monitoring import set_project_model_monitoring_credentials
61
61
  from ..utils.notifications import CustomNotificationPusher, NotificationTypes
62
62
  from .operations import (
63
63
  BuildStatus,
@@ -2105,43 +2105,15 @@ class MlrunProject(ModelObj):
2105
2105
  mlrun.get_dataitem(filepath).upload(tmp_path)
2106
2106
  remove(tmp_path)
2107
2107
 
2108
- def set_model_monitoring_credentials(
2109
- self,
2110
- access_key: str = None,
2111
- endpoint_store_connection: str = None,
2112
- stream_path: str = None,
2113
- ):
2108
+ def set_model_monitoring_credentials(self, access_key: str):
2114
2109
  """Set the credentials that will be used by the project's model monitoring
2115
2110
  infrastructure functions.
2111
+ The supplied credentials must have data access
2116
2112
 
2117
- :param access_key: Model Monitoring access key for managing user permissions
2118
- :param endpoint_store_connection: Endpoint store connection string
2119
- :param stream_path: Path to the model monitoring stream
2113
+ :param access_key: Model Monitoring access key for managing user permissions.
2120
2114
  """
2121
-
2122
- secrets_dict = {}
2123
- if access_key:
2124
- secrets_dict[
2125
- model_monitoring_constants.ProjectSecretKeys.ACCESS_KEY
2126
- ] = access_key
2127
-
2128
- if endpoint_store_connection:
2129
- secrets_dict[
2130
- model_monitoring_constants.ProjectSecretKeys.ENDPOINT_STORE_CONNECTION
2131
- ] = endpoint_store_connection
2132
-
2133
- if stream_path:
2134
- if stream_path.startswith("kafka://") and "?topic" in stream_path:
2135
- raise mlrun.errors.MLRunInvalidArgumentError(
2136
- "Custom kafka topic is not allowed"
2137
- )
2138
- secrets_dict[
2139
- model_monitoring_constants.ProjectSecretKeys.STREAM_PATH
2140
- ] = stream_path
2141
-
2142
- self.set_secrets(
2143
- secrets=secrets_dict,
2144
- provider=mlrun.api.schemas.SecretProviderName.kubernetes,
2115
+ set_project_model_monitoring_credentials(
2116
+ access_key=access_key, project=self.metadata.name
2145
2117
  )
2146
2118
 
2147
2119
  def run_function(
@@ -2608,6 +2580,72 @@ def _init_function_from_obj(func, project, name=None):
2608
2580
  return name or func.metadata.name, func
2609
2581
 
2610
2582
 
2583
+ def _init_function_from_dict_legacy(f, project):
2584
+ name = f.get("name", "")
2585
+ url = f.get("url", "")
2586
+ kind = f.get("kind", "")
2587
+ image = f.get("image", None)
2588
+ with_repo = f.get("with_repo", False)
2589
+
2590
+ if with_repo and not project.source:
2591
+ raise ValueError("project source must be specified when cloning context")
2592
+
2593
+ in_context = False
2594
+ if not url and "spec" not in f:
2595
+ raise ValueError("function missing a url or a spec")
2596
+ # We are not using the project method to obtain an absolute path here,
2597
+ # because legacy projects are built differently, and we cannot rely on them to have a spec
2598
+ if url and "://" not in url:
2599
+ if project.context and not url.startswith("/"):
2600
+ url = path.join(project.context, url)
2601
+ in_context = True
2602
+ if not path.isfile(url):
2603
+ raise OSError(f"{url} not found")
2604
+
2605
+ if "spec" in f:
2606
+ func = new_function(name, runtime=f["spec"])
2607
+ elif is_yaml_path(url) or url.startswith("db://") or url.startswith("hub://"):
2608
+ func = import_function(url)
2609
+ if image:
2610
+ func.spec.image = image
2611
+ elif url.endswith(".ipynb"):
2612
+ func = code_to_function(name, filename=url, image=image, kind=kind)
2613
+ elif url.endswith(".py"):
2614
+ if not image:
2615
+ raise ValueError(
2616
+ "image must be provided with py code files, "
2617
+ "use function object for more control/settings"
2618
+ )
2619
+ if in_context and with_repo:
2620
+ func = new_function(name, command=url, image=image, kind=kind or "job")
2621
+ else:
2622
+ func = code_to_function(name, filename=url, image=image, kind=kind or "job")
2623
+ else:
2624
+ raise ValueError(f"unsupported function url {url} or no spec")
2625
+
2626
+ if with_repo:
2627
+ func.spec.build.source = "./"
2628
+
2629
+ return _init_function_from_obj_legacy(func, project, name)
2630
+
2631
+
2632
+ def _init_function_from_obj_legacy(func, project, name=None):
2633
+ build = func.spec.build
2634
+ if project.origin_url:
2635
+ origin = project.origin_url
2636
+ try:
2637
+ if project.repo:
2638
+ origin += "#" + project.repo.head.commit.hexsha
2639
+ except Exception:
2640
+ pass
2641
+ build.code_origin = origin
2642
+ if project.name:
2643
+ func.metadata.project = project.name
2644
+ if project.tag:
2645
+ func.metadata.tag = project.tag
2646
+ return name or func.metadata.name, func
2647
+
2648
+
2611
2649
  def _has_module(handler, kind):
2612
2650
  if not handler:
2613
2651
  return False
mlrun/runtimes/base.py CHANGED
@@ -90,7 +90,6 @@ spec_fields = [
90
90
  "pythonpath",
91
91
  "disable_auto_mount",
92
92
  "allow_empty_resources",
93
- "clone_target_dir",
94
93
  ]
95
94
 
96
95
 
@@ -131,7 +130,6 @@ class FunctionSpec(ModelObj):
131
130
  default_handler=None,
132
131
  pythonpath=None,
133
132
  disable_auto_mount=False,
134
- clone_target_dir=None,
135
133
  ):
136
134
 
137
135
  self.command = command or ""
@@ -150,9 +148,6 @@ class FunctionSpec(ModelObj):
150
148
  self.entry_points = entry_points or {}
151
149
  self.disable_auto_mount = disable_auto_mount
152
150
  self.allow_empty_resources = None
153
- # the build.source is cloned/extracted to the specified clone_target_dir
154
- # if a relative path is specified, it will be enriched with a temp dir path
155
- self.clone_target_dir = clone_target_dir or ""
156
151
 
157
152
  @property
158
153
  def build(self) -> ImageBuilder:
mlrun/runtimes/daskjob.py CHANGED
@@ -106,7 +106,6 @@ class DaskSpec(KubeResourceSpec):
106
106
  tolerations=None,
107
107
  preemption_mode=None,
108
108
  security_context=None,
109
- clone_target_dir=None,
110
109
  ):
111
110
 
112
111
  super().__init__(
@@ -136,7 +135,6 @@ class DaskSpec(KubeResourceSpec):
136
135
  tolerations=tolerations,
137
136
  preemption_mode=preemption_mode,
138
137
  security_context=security_context,
139
- clone_target_dir=clone_target_dir,
140
138
  )
141
139
  self.args = args
142
140
 
@@ -141,8 +141,6 @@ class NuclioSpec(KubeResourceSpec):
141
141
  "function_handler",
142
142
  "nuclio_runtime",
143
143
  "base_image_pull",
144
- "service_type",
145
- "add_templated_ingress_host_mode",
146
144
  ]
147
145
 
148
146
  def __init__(
@@ -181,9 +179,6 @@ class NuclioSpec(KubeResourceSpec):
181
179
  tolerations=None,
182
180
  preemption_mode=None,
183
181
  security_context=None,
184
- service_type=None,
185
- add_templated_ingress_host_mode=None,
186
- clone_target_dir=None,
187
182
  ):
188
183
 
189
184
  super().__init__(
@@ -213,7 +208,6 @@ class NuclioSpec(KubeResourceSpec):
213
208
  tolerations=tolerations,
214
209
  preemption_mode=preemption_mode,
215
210
  security_context=security_context,
216
- clone_target_dir=clone_target_dir,
217
211
  )
218
212
 
219
213
  self.base_spec = base_spec or {}
@@ -224,8 +218,6 @@ class NuclioSpec(KubeResourceSpec):
224
218
  self.nuclio_runtime = None
225
219
  self.no_cache = no_cache
226
220
  self.readiness_timeout = readiness_timeout
227
- self.service_type = service_type
228
- self.add_templated_ingress_host_mode = add_templated_ingress_host_mode
229
221
 
230
222
  self.min_replicas = min_replicas or 1
231
223
  self.max_replicas = max_replicas or 4
@@ -702,22 +694,6 @@ class RemoteRuntime(KubeResource):
702
694
  """k8s priority class"""
703
695
  super().with_priority_class(name)
704
696
 
705
- def with_service_type(
706
- self, service_type: str, add_templated_ingress_host_mode: str = None
707
- ):
708
- """
709
- Enables to control the service type of the pod and the addition of templated ingress host
710
-
711
- :param service_type: service type (ClusterIP, NodePort), defaults to
712
- mlrun.mlconf.httpdb.nuclio.service_type
713
- :param add_templated_ingress_host_mode: add templated ingress host mode (never, always, onClusterIP),
714
- see mlrun.mlconf.httpdb.nuclio.add_templated_ingress_host_mode
715
- for the default and more information
716
-
717
- """
718
- self.spec.service_type = service_type
719
- self.spec.add_templated_ingress_host_mode = add_templated_ingress_host_mode
720
-
721
697
  def _get_state(
722
698
  self,
723
699
  dashboard="",
@@ -1234,9 +1210,8 @@ def deploy_nuclio_function(
1234
1210
  # if mode allows it, enrich function http trigger with an ingress
1235
1211
  enrich_function_with_ingress(
1236
1212
  function_config,
1237
- function.spec.add_templated_ingress_host_mode
1238
- or mlconf.httpdb.nuclio.add_templated_ingress_host_mode,
1239
- function.spec.service_type or mlconf.httpdb.nuclio.default_service_type,
1213
+ mlconf.httpdb.nuclio.add_templated_ingress_host_mode,
1214
+ mlconf.httpdb.nuclio.default_service_type,
1240
1215
  )
1241
1216
 
1242
1217
  try:
@@ -1402,8 +1377,7 @@ def compile_function_config(
1402
1377
 
1403
1378
  # In Nuclio >= 1.6.x default serviceType has changed to "ClusterIP".
1404
1379
  nuclio_spec.set_config(
1405
- "spec.serviceType",
1406
- function.spec.service_type or mlconf.httpdb.nuclio.default_service_type,
1380
+ "spec.serviceType", mlconf.httpdb.nuclio.default_service_type
1407
1381
  )
1408
1382
  if function.spec.readiness_timeout:
1409
1383
  nuclio_spec.set_config(
mlrun/runtimes/kubejob.py CHANGED
@@ -58,17 +58,16 @@ class KubejobRuntime(KubeResource):
58
58
  return False
59
59
 
60
60
  def with_source_archive(
61
- self, source, workdir=None, handler=None, pull_at_runtime=True, target_dir=None
61
+ self, source, workdir=None, handler=None, pull_at_runtime=True
62
62
  ):
63
63
  """load the code from git/tar/zip archive at runtime or build
64
64
 
65
- :param source: valid path to git, zip, or tar file, e.g.
66
- git://github.com/mlrun/something.git
67
- http://some/url/file.zip
68
- :param handler: default function handler
69
- :param workdir: working dir relative to the archive root (e.g. './subdir') or absolute to the image root
65
+ :param source: valid path to git, zip, or tar file, e.g.
66
+ git://github.com/mlrun/something.git
67
+ http://some/url/file.zip
68
+ :param handler: default function handler
69
+ :param workdir: working dir relative to the archive root or absolute (e.g. './subdir')
70
70
  :param pull_at_runtime: load the archive into the container at job runtime vs on build/deploy
71
- :param target_dir: target dir on runtime pod or repo clone / archive extraction
72
71
  """
73
72
  if source.endswith(".zip") and not pull_at_runtime:
74
73
  logger.warn(
@@ -80,9 +79,6 @@ class KubejobRuntime(KubeResource):
80
79
  self.spec.default_handler = handler
81
80
  if workdir:
82
81
  self.spec.workdir = workdir
83
- if target_dir:
84
- self.spec.clone_target_dir = target_dir
85
-
86
82
  self.spec.build.load_source_on_run = pull_at_runtime
87
83
  if (
88
84
  self.spec.build.base_image
@@ -90,7 +86,7 @@ class KubejobRuntime(KubeResource):
90
86
  and pull_at_runtime
91
87
  and not self.spec.image
92
88
  ):
93
- # if we load source from repo and don't need a full build use the base_image as the image
89
+ # if we load source from repo and dont need a full build use the base_image as the image
94
90
  self.spec.image = self.spec.build.base_image
95
91
  elif not pull_at_runtime:
96
92
  # clear the image so build will not be skipped
@@ -227,8 +223,6 @@ class KubejobRuntime(KubeResource):
227
223
  self.spec.build.base_image = self.spec.build.base_image or get_in(
228
224
  data, "data.spec.build.base_image"
229
225
  )
230
- # get the clone target dir in case it was enriched due to loading source
231
- self.spec.clone_target_dir = get_in(data, "data.spec.clone_target_dir")
232
226
  ready = data.get("ready", False)
233
227
  if not ready:
234
228
  logger.info(
@@ -350,7 +344,14 @@ class KubejobRuntime(KubeResource):
350
344
  new_meta = self._get_meta(runobj)
351
345
 
352
346
  self._add_secrets_to_spec_before_running(runobj)
353
- workdir = self._resolve_workdir()
347
+ workdir = self.spec.workdir
348
+ if workdir:
349
+ if self.spec.build.source and self.spec.build.load_source_on_run:
350
+ # workdir will be set AFTER the clone
351
+ workdir = None
352
+ elif not workdir.startswith("/"):
353
+ # relative path mapped to real path in the job pod
354
+ workdir = os.path.join("/mlrun", workdir)
354
355
 
355
356
  pod_spec = func_to_pod(
356
357
  self.full_image_path(
@@ -384,31 +385,6 @@ class KubejobRuntime(KubeResource):
384
385
 
385
386
  return None
386
387
 
387
- def _resolve_workdir(self):
388
- """
389
- The workdir is relative to the source root, if the source is not loaded on run then the workdir
390
- is relative to the clone target dir (where the source was copied to).
391
- Otherwise, if the source is loaded on run, the workdir is resolved on the run as well.
392
- If the workdir is absolute, keep it as is.
393
- """
394
- workdir = self.spec.workdir
395
- if self.spec.build.source and self.spec.build.load_source_on_run:
396
- # workdir will be set AFTER the clone which is done in the pre-run of local runtime
397
- return None
398
-
399
- if workdir and os.path.isabs(workdir):
400
- return workdir
401
-
402
- if self.spec.clone_target_dir:
403
- workdir = workdir or ""
404
- if workdir.startswith("./"):
405
- # TODO: use 'removeprefix' when we drop python 3.7 support
406
- # workdir.removeprefix("./")
407
- workdir = workdir[2:]
408
- return os.path.join(self.spec.clone_target_dir, workdir)
409
-
410
- return workdir
411
-
412
388
 
413
389
  def func_to_pod(image, runtime, extra_env, command, args, workdir):
414
390
  container = client.V1Container(
mlrun/runtimes/local.py CHANGED
@@ -41,7 +41,7 @@ from ..execution import MLClientCtx
41
41
  from ..model import RunObject
42
42
  from ..utils import get_handler_extended, get_in, logger, set_paths
43
43
  from ..utils.clones import extract_source
44
- from .base import BaseRuntime
44
+ from .base import BaseRuntime, FunctionSpec, spec_fields
45
45
  from .kubejob import KubejobRuntime
46
46
  from .remotesparkjob import RemoteSparkRuntime
47
47
  from .utils import RunError, global_context, log_std
@@ -172,10 +172,48 @@ class HandlerRuntime(BaseRuntime, ParallelRunner):
172
172
  return context.to_dict()
173
173
 
174
174
 
175
+ class LocalFunctionSpec(FunctionSpec):
176
+ _dict_fields = spec_fields + ["clone_target_dir"]
177
+
178
+ def __init__(
179
+ self,
180
+ command=None,
181
+ args=None,
182
+ mode=None,
183
+ default_handler=None,
184
+ pythonpath=None,
185
+ entry_points=None,
186
+ description=None,
187
+ workdir=None,
188
+ build=None,
189
+ clone_target_dir=None,
190
+ ):
191
+ super().__init__(
192
+ command=command,
193
+ args=args,
194
+ mode=mode,
195
+ build=build,
196
+ entry_points=entry_points,
197
+ description=description,
198
+ workdir=workdir,
199
+ default_handler=default_handler,
200
+ pythonpath=pythonpath,
201
+ )
202
+ self.clone_target_dir = clone_target_dir
203
+
204
+
175
205
  class LocalRuntime(BaseRuntime, ParallelRunner):
176
206
  kind = "local"
177
207
  _is_remote = False
178
208
 
209
+ @property
210
+ def spec(self) -> LocalFunctionSpec:
211
+ return self._spec
212
+
213
+ @spec.setter
214
+ def spec(self, spec):
215
+ self._spec = self._verify_dict(spec, "spec", LocalFunctionSpec)
216
+
179
217
  def to_job(self, image=""):
180
218
  struct = self.to_dict()
181
219
  obj = KubejobRuntime.from_dict(struct)
@@ -186,12 +224,12 @@ class LocalRuntime(BaseRuntime, ParallelRunner):
186
224
  def with_source_archive(self, source, workdir=None, handler=None, target_dir=None):
187
225
  """load the code from git/tar/zip archive at runtime or build
188
226
 
189
- :param source: valid path to git, zip, or tar file, e.g.
190
- git://github.com/mlrun/something.git
191
- http://some/url/file.zip
192
- :param handler: default function handler
193
- :param workdir: working dir relative to the archive root (e.g. './subdir') or absolute
194
- :param target_dir: local target dir for repo clone (by default its <current-dir>/code)
227
+ :param source: valid path to git, zip, or tar file, e.g.
228
+ git://github.com/mlrun/something.git
229
+ http://some/url/file.zip
230
+ :param handler: default function handler
231
+ :param workdir: working dir relative to the archive root or absolute (e.g. './subdir')
232
+ :param target_dir: local target dir for repo clone (by default its <current-dir>/code)
195
233
  """
196
234
  self.spec.build.source = source
197
235
  self.spec.build.load_source_on_run = True
@@ -60,7 +60,6 @@ class MPIResourceSpec(KubeResourceSpec):
60
60
  tolerations=None,
61
61
  preemption_mode=None,
62
62
  security_context=None,
63
- clone_target_dir=None,
64
63
  ):
65
64
  super().__init__(
66
65
  command=command,
@@ -89,7 +88,6 @@ class MPIResourceSpec(KubeResourceSpec):
89
88
  tolerations=tolerations,
90
89
  preemption_mode=preemption_mode,
91
90
  security_context=security_context,
92
- clone_target_dir=clone_target_dir,
93
91
  )
94
92
  self.mpi_args = mpi_args or [
95
93
  "-x",
@@ -62,7 +62,6 @@ class MPIV1ResourceSpec(MPIResourceSpec):
62
62
  tolerations=None,
63
63
  preemption_mode=None,
64
64
  security_context=None,
65
- clone_target_dir=None,
66
65
  ):
67
66
  super().__init__(
68
67
  command=command,
@@ -92,7 +91,6 @@ class MPIV1ResourceSpec(MPIResourceSpec):
92
91
  tolerations=tolerations,
93
92
  preemption_mode=preemption_mode,
94
93
  security_context=security_context,
95
- clone_target_dir=clone_target_dir,
96
94
  )
97
95
  self.clean_pod_policy = clean_pod_policy or MPIJobV1CleanPodPolicies.default()
98
96
 
mlrun/runtimes/pod.py CHANGED
@@ -135,7 +135,6 @@ class KubeResourceSpec(FunctionSpec):
135
135
  tolerations=None,
136
136
  preemption_mode=None,
137
137
  security_context=None,
138
- clone_target_dir=None,
139
138
  ):
140
139
  super().__init__(
141
140
  command=command,
@@ -149,7 +148,6 @@ class KubeResourceSpec(FunctionSpec):
149
148
  default_handler=default_handler,
150
149
  pythonpath=pythonpath,
151
150
  disable_auto_mount=disable_auto_mount,
152
- clone_target_dir=clone_target_dir,
153
151
  )
154
152
  self._volumes = {}
155
153
  self._volume_mounts = {}
@@ -58,7 +58,6 @@ class RemoteSparkSpec(KubeResourceSpec):
58
58
  tolerations=None,
59
59
  preemption_mode=None,
60
60
  security_context=None,
61
- clone_target_dir=None,
62
61
  ):
63
62
  super().__init__(
64
63
  command=command,
@@ -87,7 +86,6 @@ class RemoteSparkSpec(KubeResourceSpec):
87
86
  tolerations=tolerations,
88
87
  preemption_mode=preemption_mode,
89
88
  security_context=security_context,
90
- clone_target_dir=clone_target_dir,
91
89
  )
92
90
  self.provider = provider
93
91
 
mlrun/runtimes/serving.py CHANGED
@@ -141,9 +141,6 @@ class ServingSpec(NuclioSpec):
141
141
  tolerations=None,
142
142
  preemption_mode=None,
143
143
  security_context=None,
144
- service_type=None,
145
- add_templated_ingress_host_mode=None,
146
- clone_target_dir=None,
147
144
  ):
148
145
 
149
146
  super().__init__(
@@ -181,9 +178,6 @@ class ServingSpec(NuclioSpec):
181
178
  tolerations=tolerations,
182
179
  preemption_mode=preemption_mode,
183
180
  security_context=security_context,
184
- service_type=service_type,
185
- add_templated_ingress_host_mode=add_templated_ingress_host_mode,
186
- clone_target_dir=clone_target_dir,
187
181
  )
188
182
 
189
183
  self.models = models or {}
@@ -11,7 +11,7 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- import os.path
14
+
15
15
  import typing
16
16
  from copy import deepcopy
17
17
  from datetime import datetime
@@ -143,7 +143,6 @@ class AbstractSparkJobSpec(KubeResourceSpec):
143
143
  tolerations=None,
144
144
  preemption_mode=None,
145
145
  security_context=None,
146
- clone_target_dir=None,
147
146
  ):
148
147
 
149
148
  super().__init__(
@@ -173,7 +172,6 @@ class AbstractSparkJobSpec(KubeResourceSpec):
173
172
  tolerations=tolerations,
174
173
  preemption_mode=preemption_mode,
175
174
  security_context=security_context,
176
- clone_target_dir=clone_target_dir,
177
175
  )
178
176
 
179
177
  self._driver_resources = self.enrich_resources_with_default_pod_resources(
@@ -365,15 +363,6 @@ class AbstractSparkRuntime(KubejobRuntime):
365
363
  def _get_igz_deps(self):
366
364
  raise NotImplementedError()
367
365
 
368
- def _pre_run(self, runobj: RunObject, execution: MLClientCtx):
369
- if self.spec.build.source and self.spec.build.load_source_on_run:
370
- raise mlrun.errors.MLRunPreconditionFailedError(
371
- "Sparkjob does not support loading source code on run, "
372
- "use func.with_source_archive(pull_at_runtime=False)"
373
- )
374
-
375
- super()._pre_run(runobj, execution)
376
-
377
366
  def _run(self, runobj: RunObject, execution: MLClientCtx):
378
367
  self._validate(runobj)
379
368
 
@@ -570,11 +559,7 @@ with ctx:
570
559
 
571
560
  if self.spec.command:
572
561
  if "://" not in self.spec.command:
573
- workdir = self._resolve_workdir()
574
- self.spec.command = "local://" + os.path.join(
575
- workdir or "",
576
- self.spec.command,
577
- )
562
+ self.spec.command = "local://" + self.spec.command
578
563
  update_in(job, "spec.mainApplicationFile", self.spec.command)
579
564
 
580
565
  verify_list_and_update_in(job, "spec.arguments", self.spec.args or [], str)
@@ -804,28 +789,6 @@ with ctx:
804
789
  submission_retry_interval,
805
790
  )
806
791
 
807
- def with_source_archive(
808
- self, source, workdir=None, handler=None, pull_at_runtime=True, target_dir=None
809
- ):
810
- """load the code from git/tar/zip archive at runtime or build
811
-
812
- :param source: valid path to git, zip, or tar file, e.g.
813
- git://github.com/mlrun/something.git
814
- http://some/url/file.zip
815
- :param handler: default function handler
816
- :param workdir: working dir relative to the archive root (e.g. './subdir') or absolute to the image root
817
- :param pull_at_runtime: not supported for spark runtime, must be False
818
- :param target_dir: target dir on runtime pod for repo clone / archive extraction
819
- """
820
- if pull_at_runtime:
821
- raise mlrun.errors.MLRunInvalidArgumentError(
822
- "pull_at_runtime is not supported for spark runtime, use pull_at_runtime=False"
823
- )
824
-
825
- super().with_source_archive(
826
- source, workdir, handler, pull_at_runtime, target_dir
827
- )
828
-
829
792
  def get_pods(self, name=None, namespace=None, driver=False):
830
793
  k8s = self._get_k8s()
831
794
  namespace = k8s.resolve_namespace(namespace)
@@ -100,7 +100,6 @@ class Spark3JobSpec(AbstractSparkJobSpec):
100
100
  driver_cores=None,
101
101
  executor_cores=None,
102
102
  security_context=None,
103
- clone_target_dir=None,
104
103
  ):
105
104
 
106
105
  super().__init__(
@@ -130,7 +129,6 @@ class Spark3JobSpec(AbstractSparkJobSpec):
130
129
  tolerations=tolerations,
131
130
  preemption_mode=preemption_mode,
132
131
  security_context=security_context,
133
- clone_target_dir=clone_target_dir,
134
132
  )
135
133
 
136
134
  self.driver_resources = driver_resources or {}
mlrun/serving/__init__.py CHANGED
@@ -21,11 +21,10 @@ __all__ = [
21
21
  "TaskStep",
22
22
  "RouterStep",
23
23
  "QueueStep",
24
- "ErrorStep",
25
24
  ]
26
25
 
27
26
  from .routers import ModelRouter, VotingEnsemble # noqa
28
27
  from .server import GraphContext, GraphServer, create_graph_server # noqa
29
- from .states import ErrorStep, QueueStep, RouterStep, TaskStep # noqa
28
+ from .states import QueueStep, RouterStep, TaskStep # noqa
30
29
  from .v1_serving import MLModelServer, new_v1_model_server # noqa
31
30
  from .v2_serving import V2ModelServer # noqa