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/projects/project.py CHANGED
@@ -32,7 +32,7 @@ import dotenv
32
32
  import git
33
33
  import git.exc
34
34
  import kfp
35
- import nuclio
35
+ import nuclio.utils
36
36
  import requests
37
37
  import yaml
38
38
 
@@ -47,6 +47,7 @@ import mlrun.runtimes.pod
47
47
  import mlrun.runtimes.utils
48
48
  import mlrun.serving
49
49
  import mlrun.utils.regex
50
+ from mlrun.common.schemas import AlertConfig
50
51
  from mlrun.datastore.datastore_profile import DatastoreProfile, DatastoreProfile2Json
51
52
  from mlrun.runtimes.nuclio.function import RemoteRuntime
52
53
 
@@ -129,6 +130,7 @@ def new_project(
129
130
  save: bool = True,
130
131
  overwrite: bool = False,
131
132
  parameters: dict = None,
133
+ default_function_node_selector: dict = None,
132
134
  ) -> "MlrunProject":
133
135
  """Create a new MLRun project, optionally load it from a yaml/zip/git template
134
136
 
@@ -139,11 +141,15 @@ def new_project(
139
141
  example::
140
142
 
141
143
  # create a project with local and hub functions, a workflow, and an artifact
142
- project = mlrun.new_project("myproj", "./", init_git=True, description="my new project")
143
- project.set_function('prep_data.py', 'prep-data', image='mlrun/mlrun', handler='prep_data')
144
- project.set_function('hub://auto-trainer', 'train')
145
- project.set_artifact('data', Artifact(target_path=data_url))
146
- project.set_workflow('main', "./myflow.py")
144
+ project = mlrun.new_project(
145
+ "myproj", "./", init_git=True, description="my new project"
146
+ )
147
+ project.set_function(
148
+ "prep_data.py", "prep-data", image="mlrun/mlrun", handler="prep_data"
149
+ )
150
+ project.set_function("hub://auto-trainer", "train")
151
+ project.set_artifact("data", Artifact(target_path=data_url))
152
+ project.set_workflow("main", "./myflow.py")
147
153
  project.save()
148
154
 
149
155
  # run the "main" workflow (watch=True to wait for run completion)
@@ -153,19 +159,25 @@ def new_project(
153
159
 
154
160
  # create a new project from a zip template (can also use yaml/git templates)
155
161
  # initialize a local git, and register the git remote path
156
- project = mlrun.new_project("myproj", "./", init_git=True,
157
- remote="git://github.com/mlrun/project-demo.git",
158
- from_template="http://mysite/proj.zip")
162
+ project = mlrun.new_project(
163
+ "myproj",
164
+ "./",
165
+ init_git=True,
166
+ remote="git://github.com/mlrun/project-demo.git",
167
+ from_template="http://mysite/proj.zip",
168
+ )
159
169
  project.run("main", watch=True)
160
170
 
161
171
 
162
172
  example using project_setup.py to init the project objects::
163
173
 
164
174
  def setup(project):
165
- project.set_function('prep_data.py', 'prep-data', image='mlrun/mlrun', handler='prep_data')
166
- project.set_function('hub://auto-trainer', 'train')
167
- project.set_artifact('data', Artifact(target_path=data_url))
168
- project.set_workflow('main', "./myflow.py")
175
+ project.set_function(
176
+ "prep_data.py", "prep-data", image="mlrun/mlrun", handler="prep_data"
177
+ )
178
+ project.set_function("hub://auto-trainer", "train")
179
+ project.set_artifact("data", Artifact(target_path=data_url))
180
+ project.set_workflow("main", "./myflow.py")
169
181
  return project
170
182
 
171
183
 
@@ -182,6 +194,7 @@ def new_project(
182
194
  :param overwrite: overwrite project using 'cascade' deletion strategy (deletes project resources)
183
195
  if project with name exists
184
196
  :param parameters: key/value pairs to add to the project.spec.params
197
+ :param default_function_node_selector: defines the default node selector for scheduling functions within the project
185
198
 
186
199
  :returns: project object
187
200
  """
@@ -228,6 +241,11 @@ def new_project(
228
241
  project.spec.origin_url = url
229
242
  if description:
230
243
  project.spec.description = description
244
+
245
+ if default_function_node_selector:
246
+ for key, val in default_function_node_selector.items():
247
+ project.spec.default_function_node_selector[key] = val
248
+
231
249
  if parameters:
232
250
  # Enable setting project parameters at load time, can be used to customize the project_setup
233
251
  for key, val in parameters.items():
@@ -291,7 +309,7 @@ def load_project(
291
309
  # When using git as the url source the context directory must be an empty or
292
310
  # non-existent folder as the git repo will be cloned there
293
311
  project = load_project("./demo_proj", "git://github.com/mlrun/project-demo.git")
294
- project.run("main", arguments={'data': data_url})
312
+ project.run("main", arguments={"data": data_url})
295
313
 
296
314
 
297
315
  project_setup.py example::
@@ -430,9 +448,11 @@ def get_or_create_project(
430
448
  Usage example::
431
449
 
432
450
  # load project from the DB (if exist) or the source repo
433
- project = get_or_create_project("myproj", "./", "git://github.com/mlrun/demo-xgb-project.git")
451
+ project = get_or_create_project(
452
+ "myproj", "./", "git://github.com/mlrun/demo-xgb-project.git"
453
+ )
434
454
  project.pull("development") # pull the latest code from git
435
- project.run("main", arguments={'data': data_url}) # run the workflow "main"
455
+ project.run("main", arguments={"data": data_url}) # run the workflow "main"
436
456
 
437
457
 
438
458
  project_setup.py example::
@@ -1337,13 +1357,15 @@ class MlrunProject(ModelObj):
1337
1357
  example::
1338
1358
 
1339
1359
  # register a simple file artifact
1340
- project.set_artifact('data', target_path=data_url)
1360
+ project.set_artifact("data", target_path=data_url)
1341
1361
  # register a model artifact
1342
- project.set_artifact('model', ModelArtifact(model_file="model.pkl"), target_path=model_dir_url)
1362
+ project.set_artifact(
1363
+ "model", ModelArtifact(model_file="model.pkl"), target_path=model_dir_url
1364
+ )
1343
1365
 
1344
1366
  # register a path to artifact package (will be imported on project load)
1345
1367
  # to generate such package use `artifact.export(target_path)`
1346
- project.set_artifact('model', 'https://mystuff.com/models/mymodel.zip')
1368
+ project.set_artifact("model", "https://mystuff.com/models/mymodel.zip")
1347
1369
 
1348
1370
  :param key: artifact key/name
1349
1371
  :param artifact: mlrun Artifact object/dict (or its subclasses) or path to artifact
@@ -1562,7 +1584,9 @@ class MlrunProject(ModelObj):
1562
1584
  "age": [42, 52, 36, 24, 73],
1563
1585
  "testScore": [25, 94, 57, 62, 70],
1564
1586
  }
1565
- df = pd.DataFrame(raw_data, columns=["first_name", "last_name", "age", "testScore"])
1587
+ df = pd.DataFrame(
1588
+ raw_data, columns=["first_name", "last_name", "age", "testScore"]
1589
+ )
1566
1590
  project.log_dataset("mydf", df=df, stats=True)
1567
1591
 
1568
1592
  :param key: artifact key
@@ -1636,13 +1660,16 @@ class MlrunProject(ModelObj):
1636
1660
 
1637
1661
  example::
1638
1662
 
1639
- project.log_model("model", body=dumps(model),
1640
- model_file="model.pkl",
1641
- metrics=context.results,
1642
- training_set=training_df,
1643
- label_column='label',
1644
- feature_vector=feature_vector_uri,
1645
- labels={"app": "fraud"})
1663
+ project.log_model(
1664
+ "model",
1665
+ body=dumps(model),
1666
+ model_file="model.pkl",
1667
+ metrics=context.results,
1668
+ training_set=training_df,
1669
+ label_column="label",
1670
+ feature_vector=feature_vector_uri,
1671
+ labels={"app": "fraud"},
1672
+ )
1646
1673
 
1647
1674
  :param key: artifact key or artifact class ()
1648
1675
  :param body: will use the body as the artifact content
@@ -1891,8 +1918,9 @@ class MlrunProject(ModelObj):
1891
1918
  Create a monitoring function object without setting it to the project
1892
1919
 
1893
1920
  examples::
1894
- project.create_model_monitoring_function(application_class_name="MyApp",
1895
- image="mlrun/mlrun", name="myApp")
1921
+ project.create_model_monitoring_function(
1922
+ application_class_name="MyApp", image="mlrun/mlrun", name="myApp"
1923
+ )
1896
1924
 
1897
1925
  :param func: Code url, None refers to current Notebook
1898
1926
  :param name: Name of the function, can be specified with a tag to support
@@ -2079,14 +2107,15 @@ class MlrunProject(ModelObj):
2079
2107
  db.delete_function(project=self.name, name=fn_name)
2080
2108
  if delete_histogram_data_drift_app:
2081
2109
  db.delete_function(
2082
- project=self.name, name=mm_constants.MLRUN_HISTOGRAM_DATA_DRIFT_APP_NAME
2110
+ project=self.name,
2111
+ name=mm_constants.HistogramDataDriftApplicationConstants.NAME,
2083
2112
  )
2084
2113
 
2085
2114
  def set_function(
2086
2115
  self,
2087
2116
  func: typing.Union[str, mlrun.runtimes.BaseRuntime] = None,
2088
2117
  name: str = "",
2089
- kind: str = "",
2118
+ kind: str = "job",
2090
2119
  image: str = None,
2091
2120
  handler: str = None,
2092
2121
  with_repo: bool = None,
@@ -2106,19 +2135,20 @@ class MlrunProject(ModelObj):
2106
2135
  examples::
2107
2136
 
2108
2137
  proj.set_function(func_object)
2109
- proj.set_function('./src/mycode.py', 'ingest',
2110
- image='myrepo/ing:latest', with_repo=True)
2111
- proj.set_function('http://.../mynb.ipynb', 'train')
2112
- proj.set_function('./func.yaml')
2113
- proj.set_function('hub://get_toy_data', 'getdata')
2138
+ proj.set_function(
2139
+ "./src/mycode.py", "ingest", image="myrepo/ing:latest", with_repo=True
2140
+ )
2141
+ proj.set_function("http://.../mynb.ipynb", "train")
2142
+ proj.set_function("./func.yaml")
2143
+ proj.set_function("hub://get_toy_data", "getdata")
2114
2144
 
2115
2145
  # set function requirements
2116
2146
 
2117
2147
  # by providing a list of packages
2118
- proj.set_function('my.py', requirements=["requests", "pandas"])
2148
+ proj.set_function("my.py", requirements=["requests", "pandas"])
2119
2149
 
2120
2150
  # by providing a path to a pip requirements file
2121
- proj.set_function('my.py', requirements="requirements.txt")
2151
+ proj.set_function("my.py", requirements="requirements.txt")
2122
2152
 
2123
2153
  :param func: Function object or spec/code url, None refers to current Notebook
2124
2154
  :param name: Name of the function (under the project), can be specified with a tag to support
@@ -2173,16 +2203,13 @@ class MlrunProject(ModelObj):
2173
2203
  if func is None and not _has_module(handler, kind):
2174
2204
  # if function path is not provided and it is not a module (no ".")
2175
2205
  # use the current notebook as default
2176
- if not is_ipython:
2177
- raise ValueError(
2178
- "Function path or module must be specified (when not running inside a Notebook)"
2179
- )
2180
- from IPython import get_ipython
2206
+ if is_ipython:
2207
+ from IPython import get_ipython
2181
2208
 
2182
- kernel = get_ipython()
2183
- func = nuclio.utils.notebook_file_name(kernel)
2184
- if func.startswith(path.abspath(self.spec.context)):
2185
- func = path.relpath(func, self.spec.context)
2209
+ kernel = get_ipython()
2210
+ func = nuclio.utils.notebook_file_name(kernel)
2211
+ if func.startswith(path.abspath(self.spec.context)):
2212
+ func = path.relpath(func, self.spec.context)
2186
2213
 
2187
2214
  func = func or ""
2188
2215
 
@@ -2599,9 +2626,9 @@ class MlrunProject(ModelObj):
2599
2626
 
2600
2627
  read secrets from a source provider to be used in workflows, example::
2601
2628
 
2602
- proj.with_secrets('file', 'file.txt')
2603
- proj.with_secrets('inline', {'key': 'val'})
2604
- proj.with_secrets('env', 'ENV1,ENV2', prefix='PFX_')
2629
+ proj.with_secrets("file", "file.txt")
2630
+ proj.with_secrets("inline", {"key": "val"})
2631
+ proj.with_secrets("env", "ENV1,ENV2", prefix="PFX_")
2605
2632
 
2606
2633
  Vault secret source has several options::
2607
2634
 
@@ -2612,7 +2639,7 @@ class MlrunProject(ModelObj):
2612
2639
  The 2nd option uses the current project name as context.
2613
2640
  Can also use empty secret list::
2614
2641
 
2615
- proj.with_secrets('vault', [])
2642
+ proj.with_secrets("vault", [])
2616
2643
 
2617
2644
  This will enable access to all secrets in vault registered to the current project.
2618
2645
 
@@ -2643,17 +2670,20 @@ class MlrunProject(ModelObj):
2643
2670
  file_path: str = None,
2644
2671
  provider: typing.Union[str, mlrun.common.schemas.SecretProviderName] = None,
2645
2672
  ):
2646
- """set project secrets from dict or secrets env file
2673
+ """
2674
+ Set project secrets from dict or secrets env file
2647
2675
  when using a secrets file it should have lines in the form KEY=VALUE, comment line start with "#"
2648
2676
  V3IO paths/credentials and MLrun service API address are dropped from the secrets
2649
2677
 
2650
- example secrets file::
2678
+ example secrets file:
2679
+
2680
+ .. code-block:: shell
2651
2681
 
2652
2682
  # this is an env file
2653
- AWS_ACCESS_KEY_ID-XXXX
2683
+ AWS_ACCESS_KEY_ID=XXXX
2654
2684
  AWS_SECRET_ACCESS_KEY=YYYY
2655
2685
 
2656
- usage::
2686
+ usage:
2657
2687
 
2658
2688
  # read env vars from dict or file and set as project secrets
2659
2689
  project.set_secrets({"SECRET1": "value"})
@@ -3028,8 +3058,11 @@ class MlrunProject(ModelObj):
3028
3058
 
3029
3059
  # run functions (refer to them by name)
3030
3060
  run1 = project.run_function("myfunc", params={"x": 7})
3031
- run2 = project.run_function("train", params={"label_columns": LABELS},
3032
- inputs={"dataset":run1.outputs["data"]})
3061
+ run2 = project.run_function(
3062
+ "train",
3063
+ params={"label_columns": LABELS},
3064
+ inputs={"dataset": run1.outputs["data"]},
3065
+ )
3033
3066
 
3034
3067
  :param function: name of the function (in the project) or function object
3035
3068
  :param handler: name of the function handler
@@ -3340,7 +3373,7 @@ class MlrunProject(ModelObj):
3340
3373
  logger.warning(
3341
3374
  f"Image was successfully built, but failed to delete temporary function {function.metadata.name}."
3342
3375
  " To remove the function, attempt to manually delete it.",
3343
- exc=repr(exc),
3376
+ exc=mlrun.errors.err_to_str(exc),
3344
3377
  )
3345
3378
 
3346
3379
  return result
@@ -3417,9 +3450,9 @@ class MlrunProject(ModelObj):
3417
3450
  Examples::
3418
3451
 
3419
3452
  # Get latest version of all artifacts in project
3420
- latest_artifacts = project.list_artifacts('', tag='latest')
3453
+ latest_artifacts = project.list_artifacts("", tag="latest")
3421
3454
  # check different artifact versions for a specific artifact, return as objects list
3422
- result_versions = project.list_artifacts('results', tag='*').to_objects()
3455
+ result_versions = project.list_artifacts("results", tag="*").to_objects()
3423
3456
 
3424
3457
  :param name: Name of artifacts to retrieve. Name with '~' prefix is used as a like query, and is not
3425
3458
  case-sensitive. This means that querying for ``~name`` may return artifacts named
@@ -3469,7 +3502,7 @@ class MlrunProject(ModelObj):
3469
3502
  Examples::
3470
3503
 
3471
3504
  # Get latest version of all models in project
3472
- latest_models = project.list_models('', tag='latest')
3505
+ latest_models = project.list_models("", tag="latest")
3473
3506
 
3474
3507
 
3475
3508
  :param name: Name of artifacts to retrieve. Name with '~' prefix is used as a like query, and is not
@@ -3574,14 +3607,14 @@ class MlrunProject(ModelObj):
3574
3607
  Example::
3575
3608
 
3576
3609
  # return a list of runs matching the name and label and compare
3577
- runs = project.list_runs(name='download', labels='owner=admin')
3610
+ runs = project.list_runs(name="download", labels="owner=admin")
3578
3611
  runs.compare()
3579
3612
 
3580
3613
  # multi-label filter can also be provided
3581
- runs = project.list_runs(name='download', labels=["kind=job", "owner=admin"])
3614
+ runs = project.list_runs(name="download", labels=["kind=job", "owner=admin"])
3582
3615
 
3583
3616
  # If running in Jupyter, can use the .show() function to display the results
3584
- project.list_runs(name='').show()
3617
+ project.list_runs(name="").show()
3585
3618
 
3586
3619
 
3587
3620
  :param name: Name of the run to retrieve.
@@ -3688,7 +3721,10 @@ class MlrunProject(ModelObj):
3688
3721
  self.spec.remove_custom_packager(packager=packager)
3689
3722
 
3690
3723
  def store_api_gateway(
3691
- self, api_gateway: mlrun.runtimes.nuclio.api_gateway.APIGateway
3724
+ self,
3725
+ api_gateway: mlrun.runtimes.nuclio.api_gateway.APIGateway,
3726
+ wait_for_readiness=True,
3727
+ max_wait_time=90,
3692
3728
  ) -> mlrun.runtimes.nuclio.api_gateway.APIGateway:
3693
3729
  """
3694
3730
  Creates or updates a Nuclio API Gateway using the provided APIGateway object.
@@ -3699,7 +3735,11 @@ class MlrunProject(ModelObj):
3699
3735
  Nuclio docs here: https://docs.nuclio.io/en/latest/reference/api-gateway/http.html
3700
3736
 
3701
3737
  :param api_gateway: An instance of :py:class:`~mlrun.runtimes.nuclio.APIGateway` representing the configuration
3702
- of the API Gateway to be created
3738
+ of the API Gateway to be created or updated.
3739
+ :param wait_for_readiness: (Optional) A boolean indicating whether to wait for the API Gateway to become ready
3740
+ after creation or update (default is True)
3741
+ :param max_wait_time: (Optional) Maximum time to wait for API Gateway readiness in seconds (default is 90s)
3742
+
3703
3743
 
3704
3744
  @return: An instance of :py:class:`~mlrun.runtimes.nuclio.APIGateway` with all fields populated based on the
3705
3745
  information retrieved from the Nuclio API
@@ -3715,6 +3755,9 @@ class MlrunProject(ModelObj):
3715
3755
  api_gateway = mlrun.runtimes.nuclio.api_gateway.APIGateway.from_scheme(
3716
3756
  api_gateway_json
3717
3757
  )
3758
+ if wait_for_readiness:
3759
+ api_gateway.wait_for_readiness(max_wait_time=max_wait_time)
3760
+
3718
3761
  return api_gateway
3719
3762
 
3720
3763
  def list_api_gateways(self) -> list[mlrun.runtimes.nuclio.api_gateway.APIGateway]:
@@ -3743,7 +3786,8 @@ class MlrunProject(ModelObj):
3743
3786
  mlrun.runtimes.nuclio.APIGateway: An instance of APIGateway.
3744
3787
  """
3745
3788
 
3746
- return mlrun.db.get_run_db().get_api_gateway(name=name, project=self.name)
3789
+ gateway = mlrun.db.get_run_db().get_api_gateway(name=name, project=self.name)
3790
+ return mlrun.runtimes.nuclio.api_gateway.APIGateway.from_scheme(gateway)
3747
3791
 
3748
3792
  def delete_api_gateway(
3749
3793
  self,
@@ -3757,6 +3801,73 @@ class MlrunProject(ModelObj):
3757
3801
 
3758
3802
  mlrun.db.get_run_db().delete_api_gateway(name=name, project=self.name)
3759
3803
 
3804
+ def store_alert_config(self, alert_data: AlertConfig, alert_name=None):
3805
+ """
3806
+ Create/modify an alert.
3807
+ :param alert_data: The data of the alert.
3808
+ :param alert_name: The name of the alert.
3809
+ :return: the created/modified alert.
3810
+ """
3811
+ db = mlrun.db.get_run_db(secrets=self._secrets)
3812
+ if alert_name is None:
3813
+ alert_name = alert_data.name
3814
+ return db.store_alert_config(alert_name, alert_data.dict(), self.metadata.name)
3815
+
3816
+ def get_alert_config(self, alert_name: str) -> AlertConfig:
3817
+ """
3818
+ Retrieve an alert.
3819
+ :param alert_name: The name of the alert to retrieve.
3820
+ :return: The alert object.
3821
+ """
3822
+ db = mlrun.db.get_run_db(secrets=self._secrets)
3823
+ return db.get_alert_config(alert_name, self.metadata.name)
3824
+
3825
+ def list_alerts_configs(self):
3826
+ """
3827
+ Retrieve list of alerts of a project.
3828
+ :return: All the alerts objects of the project.
3829
+ """
3830
+ db = mlrun.db.get_run_db(secrets=self._secrets)
3831
+ return db.list_alerts_configs(self.metadata.name)
3832
+
3833
+ def delete_alert_config(
3834
+ self, alert_data: AlertConfig = None, alert_name: str = None
3835
+ ):
3836
+ """
3837
+ Delete an alert.
3838
+ :param alert_data: The data of the alert.
3839
+ :param alert_name: The name of the alert to delete.
3840
+ """
3841
+ if alert_data is None and alert_name is None:
3842
+ raise ValueError(
3843
+ "At least one of alert_data or alert_name must be provided"
3844
+ )
3845
+ if alert_data and alert_name and alert_data.name != alert_name:
3846
+ raise ValueError("Alert_data name does not match the provided alert_name")
3847
+ db = mlrun.db.get_run_db(secrets=self._secrets)
3848
+ if alert_data:
3849
+ alert_name = alert_data.name
3850
+ db.delete_alert_config(alert_name, self.metadata.name)
3851
+
3852
+ def reset_alert_config(
3853
+ self, alert_data: AlertConfig = None, alert_name: str = None
3854
+ ):
3855
+ """
3856
+ Reset an alert.
3857
+ :param alert_data: The data of the alert.
3858
+ :param alert_name: The name of the alert to reset.
3859
+ """
3860
+ if alert_data is None and alert_name is None:
3861
+ raise ValueError(
3862
+ "At least one of alert_data or alert_name must be provided"
3863
+ )
3864
+ if alert_data and alert_name and alert_data.name != alert_name:
3865
+ raise ValueError("Alert_data name does not match the provided alert_name")
3866
+ db = mlrun.db.get_run_db(secrets=self._secrets)
3867
+ if alert_data:
3868
+ alert_name = alert_data.name
3869
+ db.reset_alert_config(alert_name, self.metadata.name)
3870
+
3760
3871
  def _run_authenticated_git_action(
3761
3872
  self,
3762
3873
  action: Callable,
@@ -3933,10 +4044,6 @@ def _init_function_from_dict(
3933
4044
  tag = f.get("tag", None)
3934
4045
 
3935
4046
  has_module = _has_module(handler, kind)
3936
- if not url and "spec" not in f and not has_module:
3937
- # function must point to a file or a module or have a spec
3938
- raise ValueError("Function missing a url or a spec or a module")
3939
-
3940
4047
  relative_url = url
3941
4048
  url, in_context = project.get_item_absolute_path(url)
3942
4049
 
@@ -3996,7 +4103,7 @@ def _init_function_from_dict(
3996
4103
  tag=tag,
3997
4104
  )
3998
4105
 
3999
- elif image and kind in mlrun.runtimes.RuntimeKinds.nuclio_runtimes():
4106
+ elif kind in mlrun.runtimes.RuntimeKinds.nuclio_runtimes():
4000
4107
  func = new_function(
4001
4108
  name,
4002
4109
  command=relative_url,
@@ -4005,7 +4112,7 @@ def _init_function_from_dict(
4005
4112
  handler=handler,
4006
4113
  tag=tag,
4007
4114
  )
4008
- if kind != mlrun.runtimes.RuntimeKinds.application:
4115
+ if image and kind != mlrun.runtimes.RuntimeKinds.application:
4009
4116
  logger.info("Function code not specified, setting entry point to image")
4010
4117
  func.from_image(image)
4011
4118
  else: