mlrun 1.7.0rc7__py3-none-any.whl → 1.7.0rc11__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 (91) hide show
  1. mlrun/__init__.py +1 -0
  2. mlrun/__main__.py +2 -0
  3. mlrun/artifacts/model.py +29 -25
  4. mlrun/common/schemas/__init__.py +4 -0
  5. mlrun/common/schemas/alert.py +122 -0
  6. mlrun/common/schemas/api_gateway.py +8 -1
  7. mlrun/common/schemas/auth.py +4 -0
  8. mlrun/common/schemas/client_spec.py +1 -0
  9. mlrun/common/schemas/hub.py +7 -9
  10. mlrun/common/schemas/model_monitoring/constants.py +4 -2
  11. mlrun/{datastore/helpers.py → common/schemas/pagination.py} +11 -3
  12. mlrun/common/schemas/project.py +15 -10
  13. mlrun/config.py +35 -13
  14. mlrun/datastore/__init__.py +3 -7
  15. mlrun/datastore/base.py +6 -5
  16. mlrun/datastore/datastore_profile.py +19 -1
  17. mlrun/datastore/snowflake_utils.py +43 -0
  18. mlrun/datastore/sources.py +18 -30
  19. mlrun/datastore/targets.py +140 -12
  20. mlrun/datastore/utils.py +10 -5
  21. mlrun/datastore/v3io.py +27 -50
  22. mlrun/db/base.py +88 -2
  23. mlrun/db/httpdb.py +314 -41
  24. mlrun/db/nopdb.py +142 -0
  25. mlrun/execution.py +21 -14
  26. mlrun/feature_store/api.py +9 -5
  27. mlrun/feature_store/feature_set.py +39 -23
  28. mlrun/feature_store/feature_vector.py +2 -1
  29. mlrun/feature_store/retrieval/spark_merger.py +27 -23
  30. mlrun/feature_store/steps.py +30 -19
  31. mlrun/features.py +4 -13
  32. mlrun/frameworks/auto_mlrun/auto_mlrun.py +2 -2
  33. mlrun/frameworks/lgbm/__init__.py +1 -1
  34. mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
  35. mlrun/frameworks/lgbm/model_handler.py +1 -1
  36. mlrun/frameworks/pytorch/__init__.py +2 -2
  37. mlrun/frameworks/sklearn/__init__.py +1 -1
  38. mlrun/frameworks/tf_keras/__init__.py +1 -1
  39. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
  40. mlrun/frameworks/tf_keras/mlrun_interface.py +2 -2
  41. mlrun/frameworks/xgboost/__init__.py +1 -1
  42. mlrun/kfpops.py +2 -5
  43. mlrun/launcher/base.py +1 -1
  44. mlrun/launcher/client.py +2 -2
  45. mlrun/model.py +2 -2
  46. mlrun/model_monitoring/application.py +11 -2
  47. mlrun/model_monitoring/applications/histogram_data_drift.py +3 -3
  48. mlrun/model_monitoring/controller.py +2 -3
  49. mlrun/model_monitoring/helpers.py +3 -1
  50. mlrun/model_monitoring/stream_processing.py +0 -1
  51. mlrun/model_monitoring/writer.py +32 -0
  52. mlrun/package/packagers_manager.py +1 -0
  53. mlrun/platforms/__init__.py +1 -1
  54. mlrun/platforms/other.py +1 -1
  55. mlrun/projects/operations.py +11 -4
  56. mlrun/projects/pipelines.py +1 -1
  57. mlrun/projects/project.py +180 -73
  58. mlrun/run.py +77 -41
  59. mlrun/runtimes/__init__.py +16 -0
  60. mlrun/runtimes/base.py +4 -1
  61. mlrun/runtimes/kubejob.py +26 -121
  62. mlrun/runtimes/mpijob/abstract.py +8 -8
  63. mlrun/runtimes/nuclio/api_gateway.py +58 -8
  64. mlrun/runtimes/nuclio/application/application.py +79 -1
  65. mlrun/runtimes/nuclio/application/reverse_proxy.go +9 -1
  66. mlrun/runtimes/nuclio/function.py +20 -13
  67. mlrun/runtimes/nuclio/serving.py +11 -10
  68. mlrun/runtimes/pod.py +148 -3
  69. mlrun/runtimes/utils.py +0 -28
  70. mlrun/secrets.py +6 -2
  71. mlrun/serving/remote.py +2 -3
  72. mlrun/serving/routers.py +7 -4
  73. mlrun/serving/server.py +1 -1
  74. mlrun/serving/states.py +14 -38
  75. mlrun/serving/v2_serving.py +8 -7
  76. mlrun/utils/helpers.py +1 -1
  77. mlrun/utils/http.py +1 -1
  78. mlrun/utils/notifications/notification/base.py +12 -0
  79. mlrun/utils/notifications/notification/console.py +2 -0
  80. mlrun/utils/notifications/notification/git.py +3 -1
  81. mlrun/utils/notifications/notification/ipython.py +2 -0
  82. mlrun/utils/notifications/notification/slack.py +41 -13
  83. mlrun/utils/notifications/notification/webhook.py +11 -1
  84. mlrun/utils/retryer.py +3 -2
  85. mlrun/utils/version/version.json +2 -2
  86. {mlrun-1.7.0rc7.dist-info → mlrun-1.7.0rc11.dist-info}/METADATA +15 -15
  87. {mlrun-1.7.0rc7.dist-info → mlrun-1.7.0rc11.dist-info}/RECORD +91 -89
  88. {mlrun-1.7.0rc7.dist-info → mlrun-1.7.0rc11.dist-info}/LICENSE +0 -0
  89. {mlrun-1.7.0rc7.dist-info → mlrun-1.7.0rc11.dist-info}/WHEEL +0 -0
  90. {mlrun-1.7.0rc7.dist-info → mlrun-1.7.0rc11.dist-info}/entry_points.txt +0 -0
  91. {mlrun-1.7.0rc7.dist-info → mlrun-1.7.0rc11.dist-info}/top_level.txt +0 -0
mlrun/db/base.py CHANGED
@@ -634,6 +634,58 @@ class RunDBInterface(ABC):
634
634
  def delete_api_gateway(self, name, project=None):
635
635
  pass
636
636
 
637
+ @abstractmethod
638
+ def remote_builder(
639
+ self,
640
+ func: "mlrun.runtimes.BaseRuntime",
641
+ with_mlrun: bool,
642
+ mlrun_version_specifier: Optional[str] = None,
643
+ skip_deployed: bool = False,
644
+ builder_env: Optional[dict] = None,
645
+ force_build: bool = False,
646
+ ):
647
+ pass
648
+
649
+ @abstractmethod
650
+ def deploy_nuclio_function(
651
+ self,
652
+ func: "mlrun.runtimes.RemoteRuntime",
653
+ builder_env: Optional[dict] = None,
654
+ ):
655
+ pass
656
+
657
+ @abstractmethod
658
+ def generate_event(
659
+ self, name: str, event_data: Union[dict, mlrun.common.schemas.Event], project=""
660
+ ):
661
+ pass
662
+
663
+ @abstractmethod
664
+ def store_alert_config(
665
+ self,
666
+ alert_name: str,
667
+ alert_data: Union[dict, mlrun.common.schemas.AlertConfig],
668
+ project="",
669
+ ):
670
+ pass
671
+
672
+ @abstractmethod
673
+ def get_alert_config(self, alert_name: str, project=""):
674
+ pass
675
+
676
+ @abstractmethod
677
+ def list_alerts_configs(self, project=""):
678
+ pass
679
+
680
+ @abstractmethod
681
+ def delete_alert_config(self, alert_name: str, project=""):
682
+ pass
683
+
684
+ @abstractmethod
685
+ def reset_alert_config(self, alert_name: str, project=""):
686
+ pass
687
+
688
+ @abstractmethod
637
689
  def get_builder_status(
638
690
  self,
639
691
  func: "mlrun.runtimes.BaseRuntime",
@@ -644,6 +696,16 @@ class RunDBInterface(ABC):
644
696
  ):
645
697
  pass
646
698
 
699
+ @abstractmethod
700
+ def get_nuclio_deploy_status(
701
+ self,
702
+ func: "mlrun.runtimes.RemoteRuntime",
703
+ last_log_timestamp: float = 0.0,
704
+ verbose: bool = False,
705
+ ):
706
+ pass
707
+
708
+ @abstractmethod
647
709
  def set_run_notifications(
648
710
  self,
649
711
  project: str,
@@ -652,6 +714,7 @@ class RunDBInterface(ABC):
652
714
  ):
653
715
  pass
654
716
 
717
+ @abstractmethod
655
718
  def store_run_notifications(
656
719
  self,
657
720
  notification_objects: list[mlrun.model.Notification],
@@ -661,40 +724,60 @@ class RunDBInterface(ABC):
661
724
  ):
662
725
  pass
663
726
 
727
+ @abstractmethod
664
728
  def get_log_size(self, uid, project=""):
665
729
  pass
666
730
 
731
+ @abstractmethod
732
+ def store_alert_notifications(
733
+ self,
734
+ session,
735
+ notification_objects: list[mlrun.model.Notification],
736
+ alert_id: str,
737
+ project: str,
738
+ mask_params: bool = True,
739
+ ):
740
+ pass
741
+
742
+ @abstractmethod
667
743
  def watch_log(self, uid, project="", watch=True, offset=0):
668
744
  pass
669
745
 
746
+ @abstractmethod
670
747
  def get_datastore_profile(
671
748
  self, name: str, project: str
672
749
  ) -> Optional[mlrun.common.schemas.DatastoreProfile]:
673
750
  pass
674
751
 
752
+ @abstractmethod
675
753
  def delete_datastore_profile(
676
754
  self, name: str, project: str
677
755
  ) -> mlrun.common.schemas.DatastoreProfile:
678
756
  pass
679
757
 
758
+ @abstractmethod
680
759
  def list_datastore_profiles(
681
760
  self, project: str
682
761
  ) -> list[mlrun.common.schemas.DatastoreProfile]:
683
762
  pass
684
763
 
764
+ @abstractmethod
685
765
  def store_datastore_profile(
686
766
  self, profile: mlrun.common.schemas.DatastoreProfile, project: str
687
767
  ):
688
768
  pass
689
769
 
770
+ @abstractmethod
690
771
  def function_status(self, project, name, kind, selector):
691
772
  pass
692
773
 
774
+ @abstractmethod
693
775
  def start_function(
694
776
  self, func_url: str = None, function: "mlrun.runtimes.BaseRuntime" = None
695
777
  ):
696
778
  pass
697
779
 
780
+ @abstractmethod
698
781
  def submit_workflow(
699
782
  self,
700
783
  project: str,
@@ -713,6 +796,7 @@ class RunDBInterface(ABC):
713
796
  ) -> "mlrun.common.schemas.WorkflowResponse":
714
797
  pass
715
798
 
799
+ @abstractmethod
716
800
  def update_model_monitoring_controller(
717
801
  self,
718
802
  project: str,
@@ -721,6 +805,7 @@ class RunDBInterface(ABC):
721
805
  ):
722
806
  pass
723
807
 
808
+ @abstractmethod
724
809
  def enable_model_monitoring(
725
810
  self,
726
811
  project: str,
@@ -728,9 +813,10 @@ class RunDBInterface(ABC):
728
813
  image: str = "mlrun/mlrun",
729
814
  deploy_histogram_data_drift_app: bool = True,
730
815
  ) -> None:
731
- raise NotImplementedError
816
+ pass
732
817
 
818
+ @abstractmethod
733
819
  def deploy_histogram_data_drift_app(
734
820
  self, project: str, image: str = "mlrun/mlrun"
735
821
  ) -> None:
736
- raise NotImplementedError
822
+ pass
mlrun/db/httpdb.py CHANGED
@@ -20,6 +20,7 @@ import time
20
20
  import traceback
21
21
  import typing
22
22
  import warnings
23
+ from copy import deepcopy
23
24
  from datetime import datetime, timedelta
24
25
  from os import path, remove
25
26
  from typing import Optional, Union
@@ -282,6 +283,68 @@ class HTTPRunDB(RunDBInterface):
282
283
 
283
284
  return response
284
285
 
286
+ def paginated_api_call(
287
+ self,
288
+ method,
289
+ path,
290
+ error=None,
291
+ params=None,
292
+ body=None,
293
+ json=None,
294
+ headers=None,
295
+ timeout=45,
296
+ version=None,
297
+ ) -> typing.Generator[requests.Response, None, None]:
298
+ """
299
+ Calls the api with pagination, yielding each page of the response
300
+ """
301
+
302
+ def _api_call(_params):
303
+ return self.api_call(
304
+ method=method,
305
+ path=path,
306
+ error=error,
307
+ params=_params,
308
+ body=body,
309
+ json=json,
310
+ headers=headers,
311
+ timeout=timeout,
312
+ version=version,
313
+ )
314
+
315
+ first_page_params = deepcopy(params) or {}
316
+ first_page_params["page"] = 1
317
+ first_page_params["page-size"] = config.httpdb.pagination.default_page_size
318
+ response = _api_call(first_page_params)
319
+ page_token = response.json().get("pagination", {}).get("page-token")
320
+ if not page_token:
321
+ yield response
322
+ return
323
+
324
+ params_with_page_token = deepcopy(params) or {}
325
+ params_with_page_token["page-token"] = page_token
326
+ while page_token:
327
+ yield response
328
+ try:
329
+ response = _api_call(params_with_page_token)
330
+ except mlrun.errors.MLRunNotFoundError:
331
+ # pagination token expired
332
+ break
333
+
334
+ page_token = response.json().get("pagination", {}).get("page-token", None)
335
+
336
+ @staticmethod
337
+ def process_paginated_responses(
338
+ responses: typing.Generator[requests.Response, None, None], key: str = "data"
339
+ ) -> list[typing.Any]:
340
+ """
341
+ Processes the paginated responses and returns the combined data
342
+ """
343
+ data = []
344
+ for response in responses:
345
+ data.extend(response.json().get(key, []))
346
+ return data
347
+
285
348
  def _init_session(self, retry_on_post: bool = False):
286
349
  return mlrun.utils.HTTPSessionWithRetry(
287
350
  retry_on_exception=config.httpdb.retry_api_call_on_exception
@@ -314,7 +377,7 @@ class HTTPRunDB(RunDBInterface):
314
377
 
315
378
  For example::
316
379
 
317
- config.dbpath = config.dbpath or 'http://mlrun-api:8080'
380
+ config.dbpath = config.dbpath or "http://mlrun-api:8080"
318
381
  db = get_run_db().connect()
319
382
  """
320
383
  # hack to allow unit tests to instantiate HTTPRunDB without a real server behind
@@ -466,6 +529,7 @@ class HTTPRunDB(RunDBInterface):
466
529
  server_cfg.get("feature_store_default_targets")
467
530
  or config.feature_store.default_targets
468
531
  )
532
+ config.alerts.mode = server_cfg.get("alerts_mode") or config.alerts.mode
469
533
 
470
534
  except Exception as exc:
471
535
  logger.warning(
@@ -698,9 +762,11 @@ class HTTPRunDB(RunDBInterface):
698
762
 
699
763
  Example::
700
764
 
701
- runs = db.list_runs(name='download', project='iris', labels=['owner=admin', 'kind=job'])
765
+ runs = db.list_runs(
766
+ name="download", project="iris", labels=["owner=admin", "kind=job"]
767
+ )
702
768
  # If running in Jupyter, can use the .show() function to display the results
703
- db.list_runs(name='', project=project_name).show()
769
+ db.list_runs(name="", project=project_name).show()
704
770
 
705
771
 
706
772
  :param name: Name of the run to retrieve.
@@ -791,15 +857,15 @@ class HTTPRunDB(RunDBInterface):
791
857
  )
792
858
  error = "list runs"
793
859
  _path = self._path_of("runs", project)
794
- resp = self.api_call("GET", _path, error, params=params)
795
- return RunList(resp.json()["runs"])
860
+ responses = self.paginated_api_call("GET", _path, error, params=params)
861
+ return RunList(self.process_paginated_responses(responses, "runs"))
796
862
 
797
863
  def del_runs(self, name=None, project=None, labels=None, state=None, days_ago=0):
798
864
  """Delete a group of runs identified by the parameters of the function.
799
865
 
800
866
  Example::
801
867
 
802
- db.del_runs(state='completed')
868
+ db.del_runs(state="completed")
803
869
 
804
870
  :param name: Name of the task which the runs belong to.
805
871
  :param project: Project to which the runs belong.
@@ -944,11 +1010,13 @@ class HTTPRunDB(RunDBInterface):
944
1010
  Examples::
945
1011
 
946
1012
  # Show latest version of all artifacts in project
947
- latest_artifacts = db.list_artifacts('', tag='latest', project='iris')
1013
+ latest_artifacts = db.list_artifacts("", tag="latest", project="iris")
948
1014
  # check different artifact versions for a specific artifact
949
- result_versions = db.list_artifacts('results', tag='*', project='iris')
1015
+ result_versions = db.list_artifacts("results", tag="*", project="iris")
950
1016
  # Show artifacts with label filters - both uploaded and of binary type
951
- result_labels = db.list_artifacts('results', tag='*', project='iris', labels=['uploaded', 'type=binary'])
1017
+ result_labels = db.list_artifacts(
1018
+ "results", tag="*", project="iris", labels=["uploaded", "type=binary"]
1019
+ )
952
1020
 
953
1021
  :param name: Name of artifacts to retrieve. Name with '~' prefix is used as a like query, and is not
954
1022
  case-sensitive. This means that querying for ``~name`` may return artifacts named
@@ -1093,8 +1161,8 @@ class HTTPRunDB(RunDBInterface):
1093
1161
  }
1094
1162
  error = "list functions"
1095
1163
  path = f"projects/{project}/functions"
1096
- resp = self.api_call("GET", path, error, params=params)
1097
- return resp.json()["funcs"]
1164
+ responses = self.paginated_api_call("GET", path, error, params=params)
1165
+ return self.process_paginated_responses(responses, "funcs")
1098
1166
 
1099
1167
  def list_runtime_resources(
1100
1168
  self,
@@ -1184,7 +1252,7 @@ class HTTPRunDB(RunDBInterface):
1184
1252
  period didn't pass.
1185
1253
  :param grace_period: Grace period given to the runtime resource before they are actually removed, counted from
1186
1254
  the moment they moved to terminal state
1187
- (defaults to mlrun.config.config.runtime_resources_deletion_grace_period).
1255
+ (defaults to mlrun.mlconf.runtime_resources_deletion_grace_period).
1188
1256
 
1189
1257
  :returns: :py:class:`~mlrun.common.schemas.GroupedByProjectRuntimeResourcesOutput` listing the runtime resources
1190
1258
  that were removed.
@@ -1240,7 +1308,9 @@ class HTTPRunDB(RunDBInterface):
1240
1308
  name="run_func_on_tuesdays",
1241
1309
  kind="job",
1242
1310
  scheduled_object=get_data_func,
1243
- cron_trigger=schemas.ScheduleCronTrigger(day_of_week='tue', hour=15, minute=30),
1311
+ cron_trigger=schemas.ScheduleCronTrigger(
1312
+ day_of_week="tue", hour=15, minute=30
1313
+ ),
1244
1314
  )
1245
1315
  db.create_schedule(project_name, schedule)
1246
1316
  """
@@ -1343,21 +1413,7 @@ class HTTPRunDB(RunDBInterface):
1343
1413
  :param builder_env: Kaniko builder pod env vars dict (for config/credentials)
1344
1414
  :param force_build: Force building the image, even when no changes were made
1345
1415
  """
1346
- is_s3_source = func.spec.build.source and func.spec.build.source.startswith(
1347
- "s3://"
1348
- )
1349
- is_ecr_image = mlrun.utils.is_ecr_url(config.httpdb.builder.docker_registry)
1350
- if not func.spec.build.load_source_on_run and is_s3_source and is_ecr_image:
1351
- logger.warning(
1352
- "Building a function image to ECR and loading an S3 source to the image may require conflicting access "
1353
- "keys. Only the permissions granted to the platform's configured secret will take affect "
1354
- "(see mlrun.config.config.httpdb.builder.docker_registry_secret). "
1355
- "In case the permissions are limited to ECR scope, you may use pull_at_runtime=True instead",
1356
- source=func.spec.build.source,
1357
- load_source_on_run=func.spec.build.load_source_on_run,
1358
- default_docker_registry=config.httpdb.builder.docker_registry,
1359
- )
1360
-
1416
+ self.warn_on_s3_and_ecr_permissions_conflict(func)
1361
1417
  try:
1362
1418
  req = {
1363
1419
  "function": func.to_dict(),
@@ -1376,10 +1432,103 @@ class HTTPRunDB(RunDBInterface):
1376
1432
 
1377
1433
  if not resp.ok:
1378
1434
  logger.error(f"bad resp!!\n{resp.text}")
1379
- raise ValueError("bad function run response")
1435
+ raise ValueError("bad submit build response")
1380
1436
 
1381
1437
  return resp.json()
1382
1438
 
1439
+ def deploy_nuclio_function(
1440
+ self,
1441
+ func: mlrun.runtimes.RemoteRuntime,
1442
+ builder_env: Optional[dict] = None,
1443
+ ):
1444
+ """
1445
+ Deploy a Nuclio function.
1446
+ :param func: Function to build.
1447
+ :param builder_env: Kaniko builder pod env vars dict (for config/credentials)
1448
+ """
1449
+ func.metadata.project = func.metadata.project or config.default_project
1450
+ self.warn_on_s3_and_ecr_permissions_conflict(func)
1451
+ try:
1452
+ req = {
1453
+ "function": func.to_dict(),
1454
+ }
1455
+ if builder_env:
1456
+ req["builder_env"] = builder_env
1457
+ _path = (
1458
+ f"projects/{func.metadata.project}/nuclio/{func.metadata.name}/deploy"
1459
+ )
1460
+ resp = self.api_call("POST", _path, json=req)
1461
+ except OSError as err:
1462
+ logger.error(f"error submitting nuclio deploy task: {err_to_str(err)}")
1463
+ raise OSError(f"error: cannot submit deploy, {err_to_str(err)}")
1464
+
1465
+ if not resp.ok:
1466
+ logger.error(f"deploy nuclio - bad response:\n{resp.text}")
1467
+ raise ValueError("bad nuclio deploy response")
1468
+
1469
+ return resp.json()
1470
+
1471
+ def get_nuclio_deploy_status(
1472
+ self,
1473
+ func: mlrun.runtimes.RemoteRuntime,
1474
+ last_log_timestamp: float = 0.0,
1475
+ verbose: bool = False,
1476
+ ):
1477
+ """Retrieve the status of a deploy operation currently in progress.
1478
+
1479
+ :param func: Function object that is being built.
1480
+ :param last_log_timestamp: Last timestamp of logs that were already retrieved. Function will return only logs
1481
+ later than this parameter.
1482
+ :param verbose: Add verbose logs into the output.
1483
+
1484
+ :returns: The following parameters:
1485
+
1486
+ - Text of builder logs.
1487
+ - Timestamp of last log retrieved, to be used in subsequent calls to this function.
1488
+ """
1489
+
1490
+ try:
1491
+ params = {
1492
+ "name": normalize_name(func.metadata.name),
1493
+ "project": func.metadata.project,
1494
+ "tag": func.metadata.tag,
1495
+ "last_log_timestamp": str(last_log_timestamp),
1496
+ "verbose": bool2str(verbose),
1497
+ }
1498
+ _path = (
1499
+ f"projects/{func.metadata.project}/nuclio/{func.metadata.name}/deploy"
1500
+ )
1501
+ resp = self.api_call("GET", _path, params=params)
1502
+ except OSError as err:
1503
+ logger.error(f"error getting deploy status: {err_to_str(err)}")
1504
+ raise OSError(f"error: cannot get deploy status, {err_to_str(err)}")
1505
+
1506
+ if not resp.ok:
1507
+ logger.warning(f"failed resp, {resp.text}")
1508
+ raise RunDBError("bad function build response")
1509
+
1510
+ if resp.headers:
1511
+ func.status.state = resp.headers.get("x-mlrun-function-status", "")
1512
+ last_log_timestamp = float(
1513
+ resp.headers.get("x-mlrun-last-timestamp", "0.0")
1514
+ )
1515
+ func.status.address = resp.headers.get("x-mlrun-address", "")
1516
+ func.status.nuclio_name = resp.headers.get("x-mlrun-name", "")
1517
+ func.status.internal_invocation_urls = resp.headers.get(
1518
+ "x-mlrun-internal-invocation-urls", ""
1519
+ ).split(",")
1520
+ func.status.external_invocation_urls = resp.headers.get(
1521
+ "x-mlrun-external-invocation-urls", ""
1522
+ ).split(",")
1523
+ func.status.container_image = resp.headers.get(
1524
+ "x-mlrun-container-image", ""
1525
+ )
1526
+
1527
+ text = ""
1528
+ if resp.content:
1529
+ text = resp.content.decode()
1530
+ return text, last_log_timestamp
1531
+
1383
1532
  def get_builder_status(
1384
1533
  self,
1385
1534
  func: BaseRuntime,
@@ -1441,9 +1590,14 @@ class HTTPRunDB(RunDBInterface):
1441
1590
  func.status.container_image = resp.headers.get(
1442
1591
  "x-mlrun-container-image", ""
1443
1592
  )
1444
- else:
1445
- func.status.build_pod = resp.headers.get("builder_pod", "")
1446
- func.spec.image = resp.headers.get("function_image", "")
1593
+
1594
+ builder_pod = resp.headers.get("builder_pod", "")
1595
+ if builder_pod:
1596
+ func.status.build_pod = builder_pod
1597
+
1598
+ function_image = resp.headers.get("function_image", "")
1599
+ if function_image:
1600
+ func.spec.image = function_image
1447
1601
 
1448
1602
  text = ""
1449
1603
  if resp.content:
@@ -1506,7 +1660,7 @@ class HTTPRunDB(RunDBInterface):
1506
1660
  Retrieve updated information on project background tasks being executed.
1507
1661
  If no filter is provided, will return background tasks from the last week.
1508
1662
 
1509
- :param project: Project name (defaults to mlrun.config.config.default_project).
1663
+ :param project: Project name (defaults to mlrun.mlconf.default_project).
1510
1664
  :param state: List only background tasks whose state is specified.
1511
1665
  :param created_from: Filter by background task created time in ``[created_from, created_to]``.
1512
1666
  :param created_to: Filter by background task created time in ``[created_from, created_to]``.
@@ -2049,7 +2203,7 @@ class HTTPRunDB(RunDBInterface):
2049
2203
  not a full object.
2050
2204
  Example::
2051
2205
 
2052
- feature_set_update = {"status": {"processed" : True}}
2206
+ feature_set_update = {"status": {"processed": True}}
2053
2207
 
2054
2208
  Will apply the field ``status.processed`` to the existing object.
2055
2209
  :param project: Project which contains the modified object.
@@ -2623,11 +2777,11 @@ class HTTPRunDB(RunDBInterface):
2623
2777
  :param secrets: A set of secret values to store.
2624
2778
  Example::
2625
2779
 
2626
- secrets = {'password': 'myPassw0rd', 'aws_key': '111222333'}
2780
+ secrets = {"password": "myPassw0rd", "aws_key": "111222333"}
2627
2781
  db.create_project_secrets(
2628
2782
  "project1",
2629
2783
  provider=mlrun.common.schemas.SecretProviderName.kubernetes,
2630
- secrets=secrets
2784
+ secrets=secrets,
2631
2785
  )
2632
2786
  """
2633
2787
  path = f"projects/{project}/secrets"
@@ -3155,8 +3309,10 @@ class HTTPRunDB(RunDBInterface):
3155
3309
  metadata=mlrun.common.schemas.HubObjectMetadata(
3156
3310
  name="priv", description="a private source"
3157
3311
  ),
3158
- spec=mlrun.common.schemas.HubSourceSpec(path="/local/path/to/source", channel="development")
3159
- )
3312
+ spec=mlrun.common.schemas.HubSourceSpec(
3313
+ path="/local/path/to/source", channel="development"
3314
+ ),
3315
+ ),
3160
3316
  )
3161
3317
  db.create_hub_source(private_source)
3162
3318
 
@@ -3170,9 +3326,9 @@ class HTTPRunDB(RunDBInterface):
3170
3326
  spec=mlrun.common.schemas.HubSourceSpec(
3171
3327
  path="/local/path/to/source/2",
3172
3328
  channel="development",
3173
- credentials={...}
3174
- )
3175
- )
3329
+ credentials={...},
3330
+ ),
3331
+ ),
3176
3332
  )
3177
3333
  db.create_hub_source(another_source)
3178
3334
 
@@ -3512,6 +3668,16 @@ class HTTPRunDB(RunDBInterface):
3512
3668
  """
3513
3669
  pass
3514
3670
 
3671
+ def store_alert_notifications(
3672
+ self,
3673
+ session,
3674
+ notification_objects: list[mlrun.model.Notification],
3675
+ alert_id: str,
3676
+ project: str,
3677
+ mask_params: bool = True,
3678
+ ):
3679
+ pass
3680
+
3515
3681
  def submit_workflow(
3516
3682
  self,
3517
3683
  project: str,
@@ -3703,6 +3869,113 @@ class HTTPRunDB(RunDBInterface):
3703
3869
 
3704
3870
  self.api_call(method="PUT", path=_path, json=profile.dict())
3705
3871
 
3872
+ @staticmethod
3873
+ def warn_on_s3_and_ecr_permissions_conflict(func):
3874
+ is_s3_source = func.spec.build.source and func.spec.build.source.startswith(
3875
+ "s3://"
3876
+ )
3877
+ is_ecr_image = mlrun.utils.is_ecr_url(config.httpdb.builder.docker_registry)
3878
+ if not func.spec.build.load_source_on_run and is_s3_source and is_ecr_image:
3879
+ logger.warning(
3880
+ "Building a function image to ECR and loading an S3 source to the image may require conflicting access "
3881
+ "keys. Only the permissions granted to the platform's configured secret will take affect "
3882
+ "(see mlrun.config.config.httpdb.builder.docker_registry_secret). "
3883
+ "In case the permissions are limited to ECR scope, you may use pull_at_runtime=True instead",
3884
+ source=func.spec.build.source,
3885
+ load_source_on_run=func.spec.build.load_source_on_run,
3886
+ default_docker_registry=config.httpdb.builder.docker_registry,
3887
+ )
3888
+
3889
+ def generate_event(
3890
+ self, name: str, event_data: Union[dict, mlrun.common.schemas.Event], project=""
3891
+ ):
3892
+ """
3893
+ Generate an event.
3894
+ :param name: The name of the event.
3895
+ :param event_data: The data of the event.
3896
+ :param project: The project that the event belongs to.
3897
+ """
3898
+ project = project or config.default_project
3899
+ endpoint_path = f"projects/{project}/events/{name}"
3900
+ error_message = f"post event {project}/events/{name}"
3901
+ if isinstance(event_data, mlrun.common.schemas.Event):
3902
+ event_data = event_data.dict()
3903
+ self.api_call(
3904
+ "POST", endpoint_path, error_message, body=dict_to_json(event_data)
3905
+ )
3906
+
3907
+ def store_alert_config(
3908
+ self,
3909
+ alert_name: str,
3910
+ alert_data: Union[dict, mlrun.common.schemas.AlertConfig],
3911
+ project="",
3912
+ ):
3913
+ """
3914
+ Create/modify an alert.
3915
+ :param alert_name: The name of the alert.
3916
+ :param alert_data: The data of the alert.
3917
+ :param project: the project that the alert belongs to.
3918
+ :return: The created/modified alert.
3919
+ """
3920
+ project = project or config.default_project
3921
+ endpoint_path = f"projects/{project}/alerts/{alert_name}"
3922
+ error_message = f"put alert {project}/alerts/{alert_name}"
3923
+ if isinstance(alert_data, mlrun.common.schemas.AlertConfig):
3924
+ alert_data = alert_data.dict()
3925
+ body = _as_json(alert_data)
3926
+ response = self.api_call("PUT", endpoint_path, error_message, body=body)
3927
+ return mlrun.common.schemas.AlertConfig(**response.json())
3928
+
3929
+ def get_alert_config(self, alert_name: str, project=""):
3930
+ """
3931
+ Retrieve an alert.
3932
+ :param alert_name: The name of the alert to retrieve.
3933
+ :param project: The project that the alert belongs to.
3934
+ :return: The alert object.
3935
+ """
3936
+ project = project or config.default_project
3937
+ endpoint_path = f"projects/{project}/alerts/{alert_name}"
3938
+ error_message = f"get alert {project}/alerts/{alert_name}"
3939
+ response = self.api_call("GET", endpoint_path, error_message)
3940
+ return mlrun.common.schemas.AlertConfig(**response.json())
3941
+
3942
+ def list_alerts_configs(self, project=""):
3943
+ """
3944
+ Retrieve list of alerts of a project.
3945
+ :param project: The project name.
3946
+ :return: All the alerts objects of the project.
3947
+ """
3948
+ project = project or config.default_project
3949
+ endpoint_path = f"projects/{project}/alerts"
3950
+ error_message = f"get alerts {project}/alerts"
3951
+ response = self.api_call("GET", endpoint_path, error_message).json()
3952
+ results = []
3953
+ for item in response:
3954
+ results.append(mlrun.common.schemas.AlertConfig(**item))
3955
+ return results
3956
+
3957
+ def delete_alert_config(self, alert_name: str, project=""):
3958
+ """
3959
+ Delete an alert.
3960
+ :param alert_name: The name of the alert to delete.
3961
+ :param project: The project that the alert belongs to.
3962
+ """
3963
+ project = project or config.default_project
3964
+ endpoint_path = f"projects/{project}/alerts/{alert_name}"
3965
+ error_message = f"delete alert {project}/alerts/{alert_name}"
3966
+ self.api_call("DELETE", endpoint_path, error_message)
3967
+
3968
+ def reset_alert_config(self, alert_name: str, project=""):
3969
+ """
3970
+ Reset an alert.
3971
+ :param alert_name: The name of the alert to reset.
3972
+ :param project: The project that the alert belongs to.
3973
+ """
3974
+ project = project or config.default_project
3975
+ endpoint_path = f"projects/{project}/alerts/{alert_name}/reset"
3976
+ error_message = f"post alert {project}/alerts/{alert_name}/reset"
3977
+ self.api_call("POST", endpoint_path, error_message)
3978
+
3706
3979
 
3707
3980
  def _as_json(obj):
3708
3981
  fn = getattr(obj, "to_json", None)