mlrun 1.10.0rc18__py3-none-any.whl → 1.11.0rc16__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 (167) hide show
  1. mlrun/__init__.py +24 -3
  2. mlrun/__main__.py +0 -4
  3. mlrun/artifacts/dataset.py +2 -2
  4. mlrun/artifacts/document.py +6 -1
  5. mlrun/artifacts/llm_prompt.py +21 -15
  6. mlrun/artifacts/model.py +3 -3
  7. mlrun/artifacts/plots.py +1 -1
  8. mlrun/{model_monitoring/db/tsdb/tdengine → auth}/__init__.py +2 -3
  9. mlrun/auth/nuclio.py +89 -0
  10. mlrun/auth/providers.py +429 -0
  11. mlrun/auth/utils.py +415 -0
  12. mlrun/common/constants.py +14 -0
  13. mlrun/common/model_monitoring/helpers.py +123 -0
  14. mlrun/common/runtimes/constants.py +28 -0
  15. mlrun/common/schemas/__init__.py +14 -3
  16. mlrun/common/schemas/alert.py +2 -2
  17. mlrun/common/schemas/api_gateway.py +3 -0
  18. mlrun/common/schemas/auth.py +12 -10
  19. mlrun/common/schemas/client_spec.py +4 -0
  20. mlrun/common/schemas/constants.py +25 -0
  21. mlrun/common/schemas/frontend_spec.py +1 -8
  22. mlrun/common/schemas/function.py +34 -0
  23. mlrun/common/schemas/hub.py +33 -20
  24. mlrun/common/schemas/model_monitoring/__init__.py +2 -1
  25. mlrun/common/schemas/model_monitoring/constants.py +12 -15
  26. mlrun/common/schemas/model_monitoring/functions.py +13 -4
  27. mlrun/common/schemas/model_monitoring/model_endpoints.py +11 -0
  28. mlrun/common/schemas/pipeline.py +1 -1
  29. mlrun/common/schemas/secret.py +17 -2
  30. mlrun/common/secrets.py +95 -1
  31. mlrun/common/types.py +10 -10
  32. mlrun/config.py +69 -19
  33. mlrun/data_types/infer.py +2 -2
  34. mlrun/datastore/__init__.py +12 -5
  35. mlrun/datastore/azure_blob.py +162 -47
  36. mlrun/datastore/base.py +274 -10
  37. mlrun/datastore/datastore.py +7 -2
  38. mlrun/datastore/datastore_profile.py +84 -22
  39. mlrun/datastore/model_provider/huggingface_provider.py +225 -41
  40. mlrun/datastore/model_provider/mock_model_provider.py +87 -0
  41. mlrun/datastore/model_provider/model_provider.py +206 -74
  42. mlrun/datastore/model_provider/openai_provider.py +226 -66
  43. mlrun/datastore/s3.py +39 -18
  44. mlrun/datastore/sources.py +1 -1
  45. mlrun/datastore/store_resources.py +4 -4
  46. mlrun/datastore/storeytargets.py +17 -12
  47. mlrun/datastore/targets.py +1 -1
  48. mlrun/datastore/utils.py +25 -6
  49. mlrun/datastore/v3io.py +1 -1
  50. mlrun/db/base.py +63 -32
  51. mlrun/db/httpdb.py +373 -153
  52. mlrun/db/nopdb.py +54 -21
  53. mlrun/errors.py +4 -2
  54. mlrun/execution.py +66 -25
  55. mlrun/feature_store/api.py +1 -1
  56. mlrun/feature_store/common.py +1 -1
  57. mlrun/feature_store/feature_vector_utils.py +1 -1
  58. mlrun/feature_store/steps.py +8 -6
  59. mlrun/frameworks/_common/utils.py +3 -3
  60. mlrun/frameworks/_dl_common/loggers/logger.py +1 -1
  61. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +2 -1
  62. mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +1 -1
  63. mlrun/frameworks/_ml_common/utils.py +2 -1
  64. mlrun/frameworks/auto_mlrun/auto_mlrun.py +4 -3
  65. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +2 -1
  66. mlrun/frameworks/onnx/dataset.py +2 -1
  67. mlrun/frameworks/onnx/mlrun_interface.py +2 -1
  68. mlrun/frameworks/pytorch/callbacks/logging_callback.py +5 -4
  69. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +2 -1
  70. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +2 -1
  71. mlrun/frameworks/pytorch/utils.py +2 -1
  72. mlrun/frameworks/sklearn/metric.py +2 -1
  73. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +5 -4
  74. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +2 -1
  75. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +2 -1
  76. mlrun/hub/__init__.py +52 -0
  77. mlrun/hub/base.py +142 -0
  78. mlrun/hub/module.py +172 -0
  79. mlrun/hub/step.py +113 -0
  80. mlrun/k8s_utils.py +105 -16
  81. mlrun/launcher/base.py +15 -7
  82. mlrun/launcher/local.py +4 -1
  83. mlrun/model.py +14 -4
  84. mlrun/model_monitoring/__init__.py +0 -1
  85. mlrun/model_monitoring/api.py +65 -28
  86. mlrun/model_monitoring/applications/__init__.py +1 -1
  87. mlrun/model_monitoring/applications/base.py +299 -128
  88. mlrun/model_monitoring/applications/context.py +2 -4
  89. mlrun/model_monitoring/controller.py +132 -58
  90. mlrun/model_monitoring/db/_schedules.py +38 -29
  91. mlrun/model_monitoring/db/_stats.py +6 -16
  92. mlrun/model_monitoring/db/tsdb/__init__.py +9 -7
  93. mlrun/model_monitoring/db/tsdb/base.py +29 -9
  94. mlrun/model_monitoring/db/tsdb/preaggregate.py +234 -0
  95. mlrun/model_monitoring/db/tsdb/stream_graph_steps.py +63 -0
  96. mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_metrics_queries.py +414 -0
  97. mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_predictions_queries.py +376 -0
  98. mlrun/model_monitoring/db/tsdb/timescaledb/queries/timescaledb_results_queries.py +590 -0
  99. mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_connection.py +434 -0
  100. mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_connector.py +541 -0
  101. mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_operations.py +808 -0
  102. mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_schema.py +502 -0
  103. mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_stream.py +163 -0
  104. mlrun/model_monitoring/db/tsdb/timescaledb/timescaledb_stream_graph_steps.py +60 -0
  105. mlrun/model_monitoring/db/tsdb/timescaledb/utils/timescaledb_dataframe_processor.py +141 -0
  106. mlrun/model_monitoring/db/tsdb/timescaledb/utils/timescaledb_query_builder.py +585 -0
  107. mlrun/model_monitoring/db/tsdb/timescaledb/writer_graph_steps.py +73 -0
  108. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +20 -9
  109. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +235 -51
  110. mlrun/model_monitoring/features_drift_table.py +2 -1
  111. mlrun/model_monitoring/helpers.py +30 -6
  112. mlrun/model_monitoring/stream_processing.py +34 -28
  113. mlrun/model_monitoring/writer.py +224 -4
  114. mlrun/package/__init__.py +2 -1
  115. mlrun/platforms/__init__.py +0 -43
  116. mlrun/platforms/iguazio.py +8 -4
  117. mlrun/projects/operations.py +17 -11
  118. mlrun/projects/pipelines.py +2 -2
  119. mlrun/projects/project.py +187 -123
  120. mlrun/run.py +95 -21
  121. mlrun/runtimes/__init__.py +2 -186
  122. mlrun/runtimes/base.py +103 -25
  123. mlrun/runtimes/constants.py +225 -0
  124. mlrun/runtimes/daskjob.py +5 -2
  125. mlrun/runtimes/databricks_job/databricks_runtime.py +2 -1
  126. mlrun/runtimes/local.py +5 -2
  127. mlrun/runtimes/mounts.py +20 -2
  128. mlrun/runtimes/nuclio/__init__.py +12 -7
  129. mlrun/runtimes/nuclio/api_gateway.py +36 -6
  130. mlrun/runtimes/nuclio/application/application.py +339 -40
  131. mlrun/runtimes/nuclio/function.py +222 -72
  132. mlrun/runtimes/nuclio/serving.py +132 -42
  133. mlrun/runtimes/pod.py +213 -21
  134. mlrun/runtimes/utils.py +49 -9
  135. mlrun/secrets.py +99 -14
  136. mlrun/serving/__init__.py +2 -0
  137. mlrun/serving/remote.py +84 -11
  138. mlrun/serving/routers.py +26 -44
  139. mlrun/serving/server.py +138 -51
  140. mlrun/serving/serving_wrapper.py +6 -2
  141. mlrun/serving/states.py +997 -283
  142. mlrun/serving/steps.py +62 -0
  143. mlrun/serving/system_steps.py +149 -95
  144. mlrun/serving/v2_serving.py +9 -10
  145. mlrun/track/trackers/mlflow_tracker.py +29 -31
  146. mlrun/utils/helpers.py +292 -94
  147. mlrun/utils/http.py +9 -2
  148. mlrun/utils/notifications/notification/base.py +18 -0
  149. mlrun/utils/notifications/notification/git.py +3 -5
  150. mlrun/utils/notifications/notification/mail.py +39 -16
  151. mlrun/utils/notifications/notification/slack.py +2 -4
  152. mlrun/utils/notifications/notification/webhook.py +2 -5
  153. mlrun/utils/notifications/notification_pusher.py +3 -3
  154. mlrun/utils/version/version.json +2 -2
  155. mlrun/utils/version/version.py +3 -4
  156. {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/METADATA +63 -74
  157. {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/RECORD +161 -143
  158. mlrun/api/schemas/__init__.py +0 -259
  159. mlrun/db/auth_utils.py +0 -152
  160. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +0 -344
  161. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +0 -75
  162. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py +0 -281
  163. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +0 -1266
  164. {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/WHEEL +0 -0
  165. {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/entry_points.txt +0 -0
  166. {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/licenses/LICENSE +0 -0
  167. {mlrun-1.10.0rc18.dist-info → mlrun-1.11.0rc16.dist-info}/top_level.txt +0 -0
mlrun/db/httpdb.py CHANGED
@@ -11,9 +11,9 @@
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
-
15
14
  import enum
16
15
  import http
16
+ import os
17
17
  import re
18
18
  import time
19
19
  import traceback
@@ -24,6 +24,7 @@ from datetime import datetime, timedelta
24
24
  from os import environ, path, remove
25
25
  from typing import Literal, Optional, Union
26
26
  from urllib.parse import urlparse
27
+ from uuid import UUID
27
28
 
28
29
  import pydantic.v1
29
30
  import requests
@@ -31,6 +32,7 @@ import semver
31
32
  from pydantic.v1 import parse_obj_as
32
33
 
33
34
  import mlrun
35
+ import mlrun.auth
34
36
  import mlrun.common.constants
35
37
  import mlrun.common.formatters
36
38
  import mlrun.common.runtimes
@@ -38,13 +40,14 @@ import mlrun.common.schemas
38
40
  import mlrun.common.schemas.model_monitoring.constants as mm_constants
39
41
  import mlrun.common.schemas.model_monitoring.model_endpoints as mm_endpoints
40
42
  import mlrun.common.types
43
+ import mlrun.k8s_utils
41
44
  import mlrun.platforms
42
45
  import mlrun.projects
43
46
  import mlrun.runtimes.nuclio.api_gateway
44
47
  import mlrun.runtimes.nuclio.function
45
48
  import mlrun.utils
46
49
  from mlrun.alerts.alert import AlertConfig
47
- from mlrun.db.auth_utils import OAuthClientIDTokenProvider, StaticTokenProvider
50
+ from mlrun.common.schemas.hub import HubSourceType
48
51
  from mlrun.errors import MLRunInvalidArgumentError, err_to_str
49
52
  from mlrun.secrets import get_secret_or_env
50
53
  from mlrun_pipelines.utils import compile_pipeline
@@ -124,6 +127,11 @@ class HTTPRunDB(RunDBInterface):
124
127
  r"\/?run\/.+\/.+",
125
128
  ]
126
129
 
130
+ NON_RETRIABLE_PATHS = [
131
+ # Storing user secret tokens is not idempotent — retrying the request may result inconsistent secret storage.
132
+ r"\/?user-secrets/tokens",
133
+ ]
134
+
127
135
  def __init__(self, url):
128
136
  self.server_version = ""
129
137
  self.session = None
@@ -135,43 +143,56 @@ class HTTPRunDB(RunDBInterface):
135
143
  version.Version().get_python_version()
136
144
  )
137
145
 
146
+ self.user = None
147
+ self.password = None
148
+ self.token_provider = None
149
+ self.base_url = None
150
+ self._parsed_url = None
151
+
138
152
  self._enrich_and_validate(url)
139
153
 
140
154
  def _enrich_and_validate(self, url):
141
- parsed_url = urlparse(url)
142
- scheme = parsed_url.scheme.lower()
143
- if scheme not in ("http", "https"):
144
- raise ValueError(
145
- f"Invalid URL scheme {scheme} for HTTPRunDB, only http(s) is supported"
146
- )
147
-
148
- endpoint = parsed_url.hostname
149
- if parsed_url.port:
150
- endpoint += f":{parsed_url.port}"
151
- base_url = f"{parsed_url.scheme}://{endpoint}{parsed_url.path}"
155
+ base_url, parsed_url = self._resolve_api_urls(url)
152
156
 
153
157
  self.base_url = base_url
154
- username = parsed_url.username or config.httpdb.user
155
- password = parsed_url.password or config.httpdb.password
158
+ self._parsed_url = parsed_url
159
+ self.user = parsed_url.username or config.httpdb.user
160
+ self.password = parsed_url.password or config.httpdb.password
161
+ self._init_token_provider()
162
+
163
+ def _init_token_provider(self):
164
+ """
165
+ Initialize token provider according to current config.
166
+
167
+ Must be called after `connect()` synced config from server (client-spec), since
168
+ some auth flows (e.g. Iguazio V4 OAuth token) require values fetched from the API.
169
+ """
156
170
  self.token_provider = None
157
171
 
158
172
  if config.auth_with_client_id.enabled:
159
- self.token_provider = OAuthClientIDTokenProvider(
173
+ self.token_provider = mlrun.auth.OAuthClientIDTokenProvider(
160
174
  token_endpoint=get_secret_or_env("MLRUN_AUTH_TOKEN_ENDPOINT"),
161
175
  client_id=get_secret_or_env("MLRUN_AUTH_CLIENT_ID"),
162
176
  client_secret=get_secret_or_env("MLRUN_AUTH_CLIENT_SECRET"),
163
177
  timeout=config.auth_with_client_id.request_timeout,
164
178
  )
179
+ elif config.auth_with_oauth_token.enabled:
180
+ self.token_provider = mlrun.auth.IGTokenProvider(
181
+ token_endpoint=config.auth_token_endpoint,
182
+ timeout=config.auth_with_oauth_token.request_timeout,
183
+ )
165
184
  else:
166
185
  username, password, token = mlrun.platforms.add_or_refresh_credentials(
167
- parsed_url.hostname, username, password, config.httpdb.token
186
+ self._parsed_url.hostname,
187
+ self.user,
188
+ self.password,
189
+ config.httpdb.token,
168
190
  )
191
+ self.user = username
192
+ self.password = password
169
193
 
170
194
  if token:
171
- self.token_provider = StaticTokenProvider(token)
172
-
173
- self.user = username
174
- self.password = password
195
+ self.token_provider = mlrun.auth.StaticTokenProvider(token)
175
196
 
176
197
  def __repr__(self):
177
198
  cls = self.__class__.__name__
@@ -252,8 +273,18 @@ class HTTPRunDB(RunDBInterface):
252
273
  }
253
274
  kw["cookies"] = cookies
254
275
  else:
255
- if "Authorization" not in kw.setdefault("headers", {}):
256
- kw["headers"].update({"Authorization": "Bearer " + token})
276
+ if (
277
+ mlrun.common.schemas.HeaderNames.authorization
278
+ not in kw.setdefault("headers", {})
279
+ ):
280
+ kw["headers"].update(
281
+ {
282
+ mlrun.common.schemas.HeaderNames.authorization: (
283
+ mlrun.common.schemas.AuthorizationHeaderPrefixes.bearer
284
+ + token
285
+ )
286
+ }
287
+ )
257
288
 
258
289
  if mlrun.common.schemas.HeaderNames.client_version not in kw.setdefault(
259
290
  "headers", {}
@@ -273,10 +304,13 @@ class HTTPRunDB(RunDBInterface):
273
304
  if isinstance(dict_[key], enum.Enum):
274
305
  dict_[key] = dict_[key].value
275
306
 
276
- # if the method is POST, we need to update the session with the appropriate retry policy
277
- if not self.session or method == "POST":
278
- retry_on_post = self._is_retry_on_post_allowed(method, path)
279
- self.session = self._init_session(retry_on_post)
307
+ retry_on_post = self._is_retry_on_post_allowed(method, path)
308
+
309
+ retry_on_put = self._is_retry_put_allowed(method, path)
310
+
311
+ # if the method is POST or PUT, we need to update the session with the appropriate retry policy
312
+ if not self.session or method in ("POST", "PUT"):
313
+ self.session = self._init_session(retry_on_post, retry_on_put)
280
314
 
281
315
  try:
282
316
  response = self.session.request(
@@ -392,11 +426,12 @@ class HTTPRunDB(RunDBInterface):
392
426
  data.extend(response.json().get(key, []))
393
427
  return data, page_token
394
428
 
395
- def _init_session(self, retry_on_post: bool = False):
429
+ def _init_session(self, retry_on_post: bool = False, retry_on_put: bool = True):
396
430
  return mlrun.utils.HTTPSessionWithRetry(
397
431
  retry_on_exception=config.httpdb.retry_api_call_on_exception
398
432
  == mlrun.common.schemas.HTTPSessionRetryMode.enabled.value,
399
433
  retry_on_post=retry_on_post,
434
+ retry_on_put=retry_on_put,
400
435
  )
401
436
 
402
437
  def _path_of(self, resource, project, uid=None):
@@ -418,7 +453,28 @@ class HTTPRunDB(RunDBInterface):
418
453
  re.match(regex, path) for regex in self.RETRIABLE_POST_PATHS
419
454
  )
420
455
 
421
- def connect(self, secrets=None):
456
+ def _is_retry_put_allowed(self, method: str, path: str) -> bool:
457
+ """
458
+ Determine if PUT request to the given path should be retried.
459
+
460
+ :param method: HTTP method
461
+ :param path: API path to check
462
+ :return: True if retry is allowed, False otherwise
463
+ """
464
+ if method != "PUT":
465
+ return True
466
+
467
+ # Strip query parameters and fragment if present
468
+ parsed_path = urlparse(path).path.lstrip("/")
469
+
470
+ # If the path matches a non-retriable path, do not allow retry
471
+ for regex in self.NON_RETRIABLE_PATHS:
472
+ if re.fullmatch(regex, parsed_path):
473
+ return False
474
+
475
+ return True
476
+
477
+ def connect(self, secrets=None) -> typing.Self:
422
478
  """Connect to the MLRun API server. Must be called prior to executing any other method.
423
479
  The code utilizes the URL for the API server from the configuration - ``config.dbpath``.
424
480
 
@@ -429,7 +485,8 @@ class HTTPRunDB(RunDBInterface):
429
485
  """
430
486
  # hack to allow unit tests to instantiate HTTPRunDB without a real server behind
431
487
  if "mock-server" in self.base_url:
432
- return
488
+ return self
489
+
433
490
  resp = self.api_call("GET", "client-spec", timeout=5)
434
491
  try:
435
492
  server_cfg = resp.json()
@@ -581,6 +638,44 @@ class HTTPRunDB(RunDBInterface):
581
638
  prefix,
582
639
  store_prefix_value,
583
640
  )
641
+ config.httpdb.authentication.mode = (
642
+ server_cfg.get("authentication_mode")
643
+ or config.httpdb.authentication.mode
644
+ )
645
+
646
+ # Iguazio V4 OAuth token config auto-initialization
647
+ if (
648
+ config.httpdb.authentication.mode
649
+ == mlrun.common.types.AuthenticationMode.IGUAZIO_V4.value
650
+ ):
651
+ if not config.auth_with_oauth_token.token_file:
652
+ user_token_file = os.path.expanduser("~/.igz.yml")
653
+
654
+ # runtimes
655
+ # TODO: change to os.getenv("MLRUN_RUNTIME_KIND")
656
+ # when https://github.com/mlrun/mlrun/pull/9121 is done.
657
+ if (
658
+ mlrun.k8s_utils.is_running_inside_kubernetes_cluster()
659
+ and not os.environ.get("JPY_SESSION_NAME")
660
+ ):
661
+ user_token_file = os.path.join(
662
+ mlrun.common.constants.MLRUN_JOB_AUTH_SECRET_PATH,
663
+ mlrun.common.constants.MLRUN_JOB_AUTH_SECRET_FILE,
664
+ )
665
+
666
+ config.auth_with_oauth_token.token_file = user_token_file
667
+
668
+ # if running inside kubernetes, use the internal endpoint, otherwise use the external endpoint
669
+ if mlrun.k8s_utils.is_running_inside_kubernetes_cluster():
670
+ config.auth_token_endpoint = server_cfg.get(
671
+ "oauth_internal_token_endpoint"
672
+ )
673
+ else:
674
+ config.auth_token_endpoint = server_cfg.get(
675
+ "oauth_external_token_endpoint"
676
+ )
677
+
678
+ config.auth_with_oauth_token.enabled = True
584
679
 
585
680
  except Exception as exc:
586
681
  logger.warning(
@@ -588,6 +683,12 @@ class HTTPRunDB(RunDBInterface):
588
683
  exc=err_to_str(exc),
589
684
  traceback=traceback.format_exc(),
590
685
  )
686
+
687
+ # Initialize token provider after syncing config from server
688
+ self._init_token_provider()
689
+
690
+ if config.is_iguazio_v4_mode() and config.auth_with_oauth_token.enabled:
691
+ mlrun.secrets.sync_secret_tokens()
591
692
  return self
592
693
 
593
694
  def store_log(self, uid, project="", body=None, append=False):
@@ -1231,7 +1332,6 @@ class HTTPRunDB(RunDBInterface):
1231
1332
  format_: Optional[
1232
1333
  mlrun.common.formatters.ArtifactFormat
1233
1334
  ] = mlrun.common.formatters.ArtifactFormat.full,
1234
- limit: Optional[int] = None,
1235
1335
  partition_by: Optional[
1236
1336
  Union[mlrun.common.schemas.ArtifactPartitionByField, str]
1237
1337
  ] = None,
@@ -1284,7 +1384,6 @@ class HTTPRunDB(RunDBInterface):
1284
1384
  points to a run and is used to filter artifacts by the run that produced them when the artifact producer id
1285
1385
  is a workflow id (artifact was created as part of a workflow).
1286
1386
  :param format_: The format in which to return the artifacts. Default is 'full'.
1287
- :param limit: Deprecated - Maximum number of artifacts to return (will be removed in 1.11.0).
1288
1387
  :param partition_by: Field to group results by. When `partition_by` is specified, the `partition_sort_by`
1289
1388
  parameter must be provided as well.
1290
1389
  :param rows_per_partition: How many top rows (per sorting defined by `partition_sort_by` and `partition_order`)
@@ -1308,12 +1407,11 @@ class HTTPRunDB(RunDBInterface):
1308
1407
  tree=tree,
1309
1408
  producer_uri=producer_uri,
1310
1409
  format_=format_,
1311
- limit=limit,
1312
1410
  partition_by=partition_by,
1313
1411
  rows_per_partition=rows_per_partition,
1314
1412
  partition_sort_by=partition_sort_by,
1315
1413
  partition_order=partition_order,
1316
- return_all=not limit,
1414
+ return_all=True,
1317
1415
  parent=parent,
1318
1416
  )
1319
1417
  return artifacts
@@ -2204,7 +2302,7 @@ class HTTPRunDB(RunDBInterface):
2204
2302
  :param project: The project of the pipeline
2205
2303
  :param pipeline: Pipeline function or path to .yaml/.zip pipeline file.
2206
2304
  :param arguments: A dictionary of arguments to pass to the pipeline.
2207
- :param experiment: A name to assign for the specific experiment.
2305
+ :param experiment: (deprecated) A name to assign for the specific experiment.
2208
2306
  :param run: A name for this specific run.
2209
2307
  :param namespace: Kubernetes namespace to execute the pipeline in.
2210
2308
  :param artifact_path: A path to artifacts used by this pipeline.
@@ -2213,6 +2311,13 @@ class HTTPRunDB(RunDBInterface):
2213
2311
  workflow and all its resources are deleted)
2214
2312
  :param timeout: Timeout for the API call.
2215
2313
  """
2314
+ if experiment is not None:
2315
+ warnings.warn(
2316
+ "The 'experiment' parameter is deprecated and will be removed in 1.13.0. "
2317
+ "Pipelines are automatically scoped by project.",
2318
+ # TODO: Remove this in 1.13.0
2319
+ FutureWarning,
2320
+ )
2216
2321
 
2217
2322
  if isinstance(pipeline, str):
2218
2323
  pipe_file = pipeline
@@ -2554,50 +2659,6 @@ class HTTPRunDB(RunDBInterface):
2554
2659
  resp = self.api_call("GET", path, error_message)
2555
2660
  return FeatureSet.from_dict(resp.json())
2556
2661
 
2557
- def list_features(
2558
- self,
2559
- project: Optional[str] = None,
2560
- name: Optional[str] = None,
2561
- tag: Optional[str] = None,
2562
- entities: Optional[list[str]] = None,
2563
- labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2564
- ) -> list[dict]:
2565
- """List feature-sets which contain specific features. This function may return multiple versions of the same
2566
- feature-set if a specific tag is not requested. Note that the various filters of this function actually
2567
- refer to the feature-set object containing the features, not to the features themselves.
2568
-
2569
- :param project: Project which contains these features.
2570
- :param name: Name of the feature to look for. The name is used in a like query, and is not case-sensitive. For
2571
- example, looking for ``feat`` will return features which are named ``MyFeature`` as well as ``defeat``.
2572
- :param tag: Return feature-sets which contain the features looked for, and are tagged with the specific tag.
2573
- :param entities: Return only feature-sets which contain an entity whose name is contained in this list.
2574
- :param labels: Filter feature-sets by label key-value pairs or key existence. This can be provided as:
2575
- - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
2576
- or `{"label": None}` to check for key existence.
2577
- - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
2578
- or just `"label"` for key existence.
2579
- - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
2580
- the specified key-value pairs or key existence.
2581
- :returns: A list of mapping from feature to a digest of the feature-set, which contains the feature-set
2582
- meta-data. Multiple entries may be returned for any specific feature due to multiple tags or versions
2583
- of the feature-set.
2584
- """
2585
-
2586
- project = project or config.active_project
2587
- labels = self._parse_labels(labels)
2588
- params = {
2589
- "name": name,
2590
- "tag": tag,
2591
- "entity": entities or [],
2592
- "label": labels,
2593
- }
2594
-
2595
- path = f"projects/{project}/features"
2596
-
2597
- error_message = f"Failed listing features, project: {project}, query: {params}"
2598
- resp = self.api_call("GET", path, error_message, params=params)
2599
- return resp.json()["features"]
2600
-
2601
2662
  def list_features_v2(
2602
2663
  self,
2603
2664
  project: Optional[str] = None,
@@ -3623,7 +3684,7 @@ class HTTPRunDB(RunDBInterface):
3623
3684
  intersection {"intersect_metrics":[], "intersect_results":[]}
3624
3685
  :return: A dictionary of application metrics and/or results for the model endpoints formatted by events_format.
3625
3686
  """
3626
- path = f"projects/{project}/model-endpoints/metrics"
3687
+ path = f"projects/{project}/model-monitoring/metrics"
3627
3688
  params = {
3628
3689
  "type": type,
3629
3690
  "endpoint-id": endpoint_ids,
@@ -3647,40 +3708,6 @@ class HTTPRunDB(RunDBInterface):
3647
3708
  )
3648
3709
  return parsed_metrics_by_endpoint
3649
3710
 
3650
- def create_user_secrets(
3651
- self,
3652
- user: str,
3653
- provider: Union[
3654
- str, mlrun.common.schemas.SecretProviderName
3655
- ] = mlrun.common.schemas.SecretProviderName.vault,
3656
- secrets: Optional[dict] = None,
3657
- ):
3658
- """Create user-context secret in Vault. Please refer to :py:func:`create_project_secrets` for more details
3659
- and status of this functionality.
3660
-
3661
- Note:
3662
- This method is currently in technical preview, and requires a HashiCorp Vault infrastructure
3663
- properly set up and connected to the MLRun API server.
3664
-
3665
- :param user: The user context for which to generate the infra and store secrets.
3666
- :param provider: The name of the secrets-provider to work with. Currently only ``vault`` is supported.
3667
- :param secrets: A set of secret values to store within the Vault.
3668
- """
3669
- path = "user-secrets"
3670
- secrets_creation_request = mlrun.common.schemas.UserSecretCreationRequest(
3671
- user=user,
3672
- provider=provider,
3673
- secrets=secrets,
3674
- )
3675
- body = secrets_creation_request.dict()
3676
- error_message = f"Failed creating user secrets - {user}"
3677
- self.api_call(
3678
- "POST",
3679
- path,
3680
- error_message,
3681
- body=dict_to_json(body),
3682
- )
3683
-
3684
3711
  @staticmethod
3685
3712
  def _validate_version_compatibility(server_version, client_version) -> bool:
3686
3713
  try:
@@ -3813,7 +3840,9 @@ class HTTPRunDB(RunDBInterface):
3813
3840
  tsdb_metrics: bool = False,
3814
3841
  metric_list: Optional[list[str]] = None,
3815
3842
  top_level: bool = False,
3816
- mode: mm_constants.EndpointMode = None,
3843
+ modes: Optional[
3844
+ Union[mm_constants.EndpointMode, list[mm_constants.EndpointMode]]
3845
+ ] = None,
3817
3846
  uids: Optional[list[str]] = None,
3818
3847
  latest_only: bool = False,
3819
3848
  ) -> mlrun.common.schemas.ModelEndpointList:
@@ -3834,8 +3863,8 @@ class HTTPRunDB(RunDBInterface):
3834
3863
  If tsdb_metrics=False, this parameter will be ignored and no tsdb metrics
3835
3864
  will be included.
3836
3865
  :param top_level: Whether to return only top level model endpoints.
3837
- :param mode: Specifies the mode of the model endpoint. Can be "real-time", "batch", or both if set
3838
- to None.
3866
+ :param modes: Specifies the modes of the model endpoints. Can be "real-time" (0), "batch" (1),
3867
+ "batch_legacy" (2). If set to None, all are included.
3839
3868
  :param uids: A list of unique ids to filter by.
3840
3869
  :param latest_only: Whether to return only the latest model endpoint version.
3841
3870
  :return: A list of model endpoints.
@@ -3844,6 +3873,13 @@ class HTTPRunDB(RunDBInterface):
3844
3873
  labels = self._parse_labels(labels)
3845
3874
  if names and isinstance(names, str):
3846
3875
  names = [names]
3876
+ if modes:
3877
+ # Ensure backward compatibility with Python 3.9 clients by converting IntEnum modes to integer values
3878
+ modes = (
3879
+ [modes.value]
3880
+ if isinstance(modes, mm_constants.EndpointMode)
3881
+ else [mode.value for mode in modes]
3882
+ )
3847
3883
  response = self.api_call(
3848
3884
  method=mlrun.common.types.HTTPMethod.GET,
3849
3885
  path=path,
@@ -3859,7 +3895,7 @@ class HTTPRunDB(RunDBInterface):
3859
3895
  "tsdb-metrics": tsdb_metrics,
3860
3896
  "metric": metric_list,
3861
3897
  "top-level": top_level,
3862
- "mode": mode,
3898
+ "mode": modes,
3863
3899
  "uid": uids,
3864
3900
  "latest-only": latest_only,
3865
3901
  },
@@ -3968,6 +4004,13 @@ class HTTPRunDB(RunDBInterface):
3968
4004
  raise MLRunInvalidArgumentError(
3969
4005
  "Either endpoint_uid or function_name and function_tag must be provided"
3970
4006
  )
4007
+ if uid:
4008
+ try:
4009
+ UUID(uid)
4010
+ except (ValueError, TypeError):
4011
+ raise MLRunInvalidArgumentError(
4012
+ "endpoint_id must be a valid UUID string"
4013
+ )
3971
4014
 
3972
4015
  def update_model_monitoring_controller(
3973
4016
  self,
@@ -4115,7 +4158,7 @@ class HTTPRunDB(RunDBInterface):
4115
4158
  response = self.api_call(
4116
4159
  method=mlrun.common.types.HTTPMethod.DELETE,
4117
4160
  path=f"projects/{project}/model-monitoring/functions",
4118
- params={"functions": functions},
4161
+ params={"function": functions},
4119
4162
  )
4120
4163
  deletion_failed = False
4121
4164
  if response.status_code == http.HTTPStatus.ACCEPTED:
@@ -4157,6 +4200,26 @@ class HTTPRunDB(RunDBInterface):
4157
4200
  params={**credentials, "replace_creds": replace_creds},
4158
4201
  )
4159
4202
 
4203
+ def delete_model_monitoring_metrics(
4204
+ self,
4205
+ project: str,
4206
+ application_name: str,
4207
+ endpoint_ids: Optional[list[str]] = None,
4208
+ ) -> None:
4209
+ """
4210
+ Delete model endpoints metrics values.
4211
+
4212
+ :param project: The name of the project.
4213
+ :param application_name: The name of the application.
4214
+ :param endpoint_ids: The unique IDs of the model endpoints to delete metrics values from. If none is
4215
+ provided, the metrics values will be deleted from all project's model endpoints.
4216
+ """
4217
+ self.api_call(
4218
+ method=mlrun.common.types.HTTPMethod.DELETE,
4219
+ path=f"projects/{project}/model-monitoring/metrics",
4220
+ params={"endpoint-id": endpoint_ids, "application-name": application_name},
4221
+ )
4222
+
4160
4223
  def get_monitoring_function_summaries(
4161
4224
  self,
4162
4225
  project: str,
@@ -4171,8 +4234,12 @@ class HTTPRunDB(RunDBInterface):
4171
4234
  Get monitoring function summaries for the specified project.
4172
4235
 
4173
4236
  :param project: The name of the project.
4174
- :param start: Start time for filtering the results (optional).
4175
- :param end: End time for filtering the results (optional).
4237
+ :param start: The start time of the monitoring applications’ statistics.
4238
+ If not defined, the default is 24 hours ago.
4239
+ Required timezone, applicable only when `include_stats` is set to True.
4240
+ :param end: The end time of the monitoring applications’ statistics.
4241
+ If not defined, the default is now.
4242
+ Required timezone, applicable only when `include_stats` is set to True.
4176
4243
  :param names: List of function names to filter by (optional).
4177
4244
  :param labels: Labels to filter by (optional).
4178
4245
  :param include_stats: Whether to include statistics in the response (default is False).
@@ -4213,12 +4280,14 @@ class HTTPRunDB(RunDBInterface):
4213
4280
  ) -> FunctionSummary:
4214
4281
  """
4215
4282
  Get a monitoring function summary for the specified project and function.
4216
- :param project: The name of the project.
4217
- :param function_name: The name of the function.
4218
- :param start: Start time for filtering the results (optional).
4219
- :param end: End time for filtering the results (optional).
4220
- :param include_latest_metrics: Whether to include the latest metrics in the response (default is False).
4221
4283
 
4284
+ :param project: The name of the project.
4285
+ :param function_name: The name of the function.
4286
+ :param start: The start time of the monitoring application's statistics.
4287
+ If not defined, the default is 24 hours ago. Required timezone.
4288
+ :param end: The end time of the monitoring application's statistics.
4289
+ If not defined, the default is now. Required timezone.
4290
+ :param include_latest_metrics: Whether to include the latest metrics in the response (default is False).
4222
4291
  :return: A FunctionSummary object containing information about the monitoring function.
4223
4292
  """
4224
4293
 
@@ -4323,6 +4392,7 @@ class HTTPRunDB(RunDBInterface):
4323
4392
  item_name: Optional[str] = None,
4324
4393
  tag: Optional[str] = None,
4325
4394
  version: Optional[str] = None,
4395
+ item_type: HubSourceType = HubSourceType.functions,
4326
4396
  ) -> list[mlrun.common.schemas.hub.IndexedHubSource]:
4327
4397
  """
4328
4398
  List hub sources in the MLRun DB.
@@ -4330,6 +4400,7 @@ class HTTPRunDB(RunDBInterface):
4330
4400
  :param item_name: Sources contain this item will be returned, If not provided all sources will be returned.
4331
4401
  :param tag: Item tag to filter by, supported only if item name is provided.
4332
4402
  :param version: Item version to filter by, supported only if item name is provided and tag is not.
4403
+ :param item_type: Item type to filter by, supported only if item name is provided.
4333
4404
 
4334
4405
  :returns: List of indexed hub sources.
4335
4406
  """
@@ -4337,6 +4408,7 @@ class HTTPRunDB(RunDBInterface):
4337
4408
  params = {}
4338
4409
  if item_name:
4339
4410
  params["item-name"] = normalize_name(item_name)
4411
+ params["item-type"] = item_type
4340
4412
  if tag:
4341
4413
  params["tag"] = tag
4342
4414
  if version:
@@ -4375,6 +4447,7 @@ class HTTPRunDB(RunDBInterface):
4375
4447
  version: Optional[str] = None,
4376
4448
  tag: Optional[str] = None,
4377
4449
  force_refresh: bool = False,
4450
+ object_type: HubSourceType = HubSourceType.functions,
4378
4451
  ):
4379
4452
  """
4380
4453
  Retrieve the item catalog for a specified hub source.
@@ -4387,6 +4460,7 @@ class HTTPRunDB(RunDBInterface):
4387
4460
  rather than rely on cached information which may exist from previous get requests. For example,
4388
4461
  if the source was re-built,
4389
4462
  this will make the server get the updated information. Default is ``False``.
4463
+ :param object_type: Type of object to retrieve from the hub source (e.g: functions, modules).
4390
4464
  :returns: :py:class:`~mlrun.common.schemas.hub.HubCatalog` object, which is essentially a list
4391
4465
  of :py:class:`~mlrun.common.schemas.hub.HubItem` entries.
4392
4466
  """
@@ -4395,6 +4469,7 @@ class HTTPRunDB(RunDBInterface):
4395
4469
  "version": version,
4396
4470
  "tag": tag,
4397
4471
  "force-refresh": force_refresh,
4472
+ "object_type": object_type,
4398
4473
  }
4399
4474
  response = self.api_call(method="GET", path=path, params=params)
4400
4475
  return mlrun.common.schemas.HubCatalog(**response.json())
@@ -4406,6 +4481,7 @@ class HTTPRunDB(RunDBInterface):
4406
4481
  version: Optional[str] = None,
4407
4482
  tag: str = "latest",
4408
4483
  force_refresh: bool = False,
4484
+ item_type: HubSourceType = HubSourceType.functions,
4409
4485
  ):
4410
4486
  """
4411
4487
  Retrieve a specific hub item.
@@ -4417,13 +4493,15 @@ class HTTPRunDB(RunDBInterface):
4417
4493
  :param force_refresh: Make the server fetch the information from the actual hub
4418
4494
  source, rather than
4419
4495
  rely on cached information. Default is ``False``.
4496
+ :param item_type: The type of item to retrieve from the hub source (e.g: functions, modules).
4420
4497
  :returns: :py:class:`~mlrun.common.schemas.hub.HubItem`.
4421
4498
  """
4422
- path = (f"hub/sources/{source_name}/items/{item_name}",)
4499
+ path = f"hub/sources/{source_name}/items/{item_name}"
4423
4500
  params = {
4424
4501
  "version": version,
4425
4502
  "tag": tag,
4426
4503
  "force-refresh": force_refresh,
4504
+ "item_type": item_type,
4427
4505
  }
4428
4506
  response = self.api_call(method="GET", path=path, params=params)
4429
4507
  return mlrun.common.schemas.HubItem(**response.json())
@@ -4435,6 +4513,7 @@ class HTTPRunDB(RunDBInterface):
4435
4513
  asset_name: str,
4436
4514
  version: Optional[str] = None,
4437
4515
  tag: str = "latest",
4516
+ item_type: HubSourceType = HubSourceType.functions,
4438
4517
  ):
4439
4518
  """
4440
4519
  Get hub asset from item.
@@ -4444,13 +4523,14 @@ class HTTPRunDB(RunDBInterface):
4444
4523
  :param asset_name: Name of the asset to retrieve.
4445
4524
  :param version: Get a specific version of the item. Default is ``None``.
4446
4525
  :param tag: Get a specific version of the item identified by tag. Default is ``latest``.
4447
-
4526
+ :param item_type: The type of item to retrieve from the hub source (e.g: functions, modules).
4448
4527
  :returns: http response with the asset in the content attribute
4449
4528
  """
4450
4529
  path = f"hub/sources/{source_name}/items/{item_name}/assets/{asset_name}"
4451
4530
  params = {
4452
4531
  "version": version,
4453
4532
  "tag": tag,
4533
+ "item_type": item_type,
4454
4534
  }
4455
4535
  response = self.api_call(method="GET", path=path, params=params)
4456
4536
  return response
@@ -5205,7 +5285,7 @@ class HTTPRunDB(RunDBInterface):
5205
5285
 
5206
5286
  :return: A ModelEndpointDriftValues object containing the drift counts over time.
5207
5287
  """
5208
- endpoint_path = f"projects/{project}/model-endpoints/drift-over-time"
5288
+ endpoint_path = f"projects/{project}/model-monitoring/drift-over-time"
5209
5289
  error_message = f"Failed retrieving drift data for {project}"
5210
5290
  response = self.api_call(
5211
5291
  method="GET",
@@ -5217,6 +5297,152 @@ class HTTPRunDB(RunDBInterface):
5217
5297
  **response.json()
5218
5298
  )
5219
5299
 
5300
+ @mlrun.utils.iguazio_v4_only
5301
+ def store_secret_token(
5302
+ self,
5303
+ secret_token: mlrun.common.schemas.SecretToken,
5304
+ log_warning: bool = True,
5305
+ force: bool = False,
5306
+ ) -> mlrun.common.schemas.StoreSecretTokensResponse:
5307
+ """
5308
+ Store or update a single secret token in the MLRun backend.
5309
+
5310
+ Example::
5311
+
5312
+ from mlrun.common.schemas import SecretToken
5313
+
5314
+ secret = SecretToken(name="my-token", token="dummy-token")
5315
+ db.store_secret_token(secret)
5316
+
5317
+ :param secret_token: A SecretToken object with name and token fields.
5318
+ :param force: Whether to force update the token if it already exists. Defaults to False.
5319
+ :param log_warning: Whether to log a warning about local config sync. Defaults to True.
5320
+ :return: A structured response indicating which tokens were created, updated, or skipped.
5321
+ """
5322
+ if not secret_token:
5323
+ raise MLRunInvalidArgumentError("No secret token provided")
5324
+
5325
+ response = self._store_secret_tokens(
5326
+ secret_tokens=[secret_token],
5327
+ force=force,
5328
+ error=f"store user secret token {secret_token.name}",
5329
+ )
5330
+
5331
+ # Only log if the token was created or updated
5332
+ if log_warning and (
5333
+ secret_token.name in response.created_tokens
5334
+ or secret_token.name in response.updated_tokens
5335
+ ):
5336
+ logger.warning(
5337
+ f"Token '{secret_token.name}' was stored in the backend, "
5338
+ f"but the local configuration file ({mlrun.mlconf.auth_with_oauth_token.token_file}) was not "
5339
+ "updated. Update it manually or run `mlrun.sync_secret_tokens()` to sync your local environment."
5340
+ )
5341
+ # maybe the response should not be a list?
5342
+ return response
5343
+
5344
+ @mlrun.utils.iguazio_v4_only
5345
+ def store_secret_tokens(
5346
+ self,
5347
+ secret_tokens: list[mlrun.common.schemas.SecretToken],
5348
+ log_warning: bool = True,
5349
+ force: bool = False,
5350
+ ) -> mlrun.common.schemas.StoreSecretTokensResponse:
5351
+ """
5352
+ Store or update multiple secret tokens in the MLRun backend.
5353
+
5354
+ Example::
5355
+
5356
+ from mlrun.common.schemas import SecretToken
5357
+
5358
+ tokens = [
5359
+ SecretToken(name="token1", token="dummy-token-1"),
5360
+ SecretToken(name="token2", token="dummy-token-2"),
5361
+ ]
5362
+ db.store_secret_tokens(tokens)
5363
+
5364
+ :param secret_tokens: List of SecretToken objects with 'name' and 'token' fields.
5365
+ :param force: Whether to force update tokens if they already exist. Defaults to False.
5366
+ :param log_warning: Whether to log a warning about local config file sync. Defaults to True.
5367
+ :return: StoreSecretTokensResponse object indicating which tokens were created, updated, or skipped.
5368
+ """
5369
+ if not secret_tokens:
5370
+ raise MLRunInvalidArgumentError("No secret tokens provided")
5371
+
5372
+ response = self._store_secret_tokens(
5373
+ secret_tokens=secret_tokens,
5374
+ force=force,
5375
+ error="store multiple user secret tokens",
5376
+ )
5377
+
5378
+ # Only log a warning if at least one token was actually created or updated
5379
+ if log_warning and (response.created_tokens or response.updated_tokens):
5380
+ affected_tokens = response.created_tokens + response.updated_tokens
5381
+ token_names = "', '".join(affected_tokens)
5382
+ logger.warning(
5383
+ f"Tokens '{token_names}' were stored in the backend, "
5384
+ f"but the local configuration file ({mlrun.mlconf.auth_with_oauth_token.token_file}) was not "
5385
+ "updated. Update it manually or run `mlrun.sync_secret_tokens()` to sync your local environment."
5386
+ )
5387
+
5388
+ return response
5389
+
5390
+ @mlrun.utils.iguazio_v4_only
5391
+ def list_secret_tokens(
5392
+ self,
5393
+ ) -> mlrun.common.schemas.ListSecretTokensResponse:
5394
+ """
5395
+ List all secret tokens for the current user.
5396
+ """
5397
+ endpoint_path = "user-secrets/tokens"
5398
+ response = self.api_call(
5399
+ mlrun.common.types.HTTPMethod.GET,
5400
+ endpoint_path,
5401
+ "list user secret tokens",
5402
+ )
5403
+
5404
+ return mlrun.common.schemas.ListSecretTokensResponse(**response.json())
5405
+
5406
+ @mlrun.utils.iguazio_v4_only
5407
+ def revoke_secret_token(self, token_name: str) -> None:
5408
+ endpoint_path = f"user-secrets/tokens/{token_name}"
5409
+ self.api_call(
5410
+ mlrun.common.types.HTTPMethod.DELETE,
5411
+ endpoint_path,
5412
+ "delete user secret token",
5413
+ )
5414
+
5415
+ @mlrun.utils.iguazio_v4_only
5416
+ def get_secret_token(
5417
+ self,
5418
+ token_name: str,
5419
+ username: Optional[str] = None,
5420
+ ) -> mlrun.common.schemas.SecretToken:
5421
+ raise NotImplementedError(
5422
+ "Getting secret token is not supported for security reasons."
5423
+ )
5424
+
5425
+ @mlrun.utils.iguazio_v4_only
5426
+ def _store_secret_tokens(
5427
+ self,
5428
+ secret_tokens: list[mlrun.common.schemas.SecretToken],
5429
+ error: str,
5430
+ force: bool = False,
5431
+ ) -> mlrun.common.schemas.StoreSecretTokensResponse:
5432
+ body = [token.dict() for token in secret_tokens]
5433
+ params = {"force": force} # send as query param
5434
+ endpoint_path = "user-secrets/tokens"
5435
+
5436
+ response = self.api_call(
5437
+ mlrun.common.types.HTTPMethod.PUT,
5438
+ endpoint_path,
5439
+ error,
5440
+ params=params,
5441
+ body=dict_to_json(body),
5442
+ )
5443
+
5444
+ return mlrun.common.schemas.StoreSecretTokensResponse(**response.json())
5445
+
5220
5446
  @staticmethod
5221
5447
  def _parse_labels(
5222
5448
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]],
@@ -5257,7 +5483,6 @@ class HTTPRunDB(RunDBInterface):
5257
5483
  format_: Optional[
5258
5484
  mlrun.common.formatters.ArtifactFormat
5259
5485
  ] = mlrun.common.formatters.ArtifactFormat.full,
5260
- limit: Optional[int] = None,
5261
5486
  partition_by: Optional[
5262
5487
  Union[mlrun.common.schemas.ArtifactPartitionByField, str]
5263
5488
  ] = None,
@@ -5278,13 +5503,6 @@ class HTTPRunDB(RunDBInterface):
5278
5503
  project = project or config.active_project
5279
5504
  labels = self._parse_labels(labels)
5280
5505
 
5281
- if limit:
5282
- # TODO: Remove this in 1.11.0
5283
- warnings.warn(
5284
- "'limit' is deprecated and will be removed in 1.11.0. Use 'page' and 'page_size' instead.",
5285
- FutureWarning,
5286
- )
5287
-
5288
5506
  params = {
5289
5507
  "name": name,
5290
5508
  "tag": tag,
@@ -5298,7 +5516,6 @@ class HTTPRunDB(RunDBInterface):
5298
5516
  "producer_uri": producer_uri,
5299
5517
  "since": datetime_to_iso(since),
5300
5518
  "until": datetime_to_iso(until),
5301
- "limit": limit,
5302
5519
  "page": page,
5303
5520
  "page-size": page_size,
5304
5521
  "page-token": page_token,
@@ -5550,24 +5767,27 @@ class HTTPRunDB(RunDBInterface):
5550
5767
  if page_params.get("page-token") is None and page_params.get("page") is None:
5551
5768
  page_params["page"] = 1
5552
5769
  if page_params.get("page-size") is None:
5553
- page_size = config.httpdb.pagination.default_page_size
5554
-
5555
- if page_params.get("limit") is not None:
5556
- page_size = page_params["limit"]
5770
+ page_params["page-size"] = config.httpdb.pagination.default_page_size
5557
5771
 
5558
- # limit and page/page size are conflicting
5559
- page_params.pop("limit")
5560
- page_params["page-size"] = page_size
5772
+ return page_params
5561
5773
 
5562
- # this may happen only when page-size was explicitly set along with limit
5563
- # this is to ensure we will not get stopped by API on similar below validation
5564
- # but rather simply fallback to use page-size.
5565
- if page_params.get("page-size") and page_params.get("limit"):
5566
- logger.warning(
5567
- "Both 'limit' and 'page-size' are provided, using 'page-size'."
5774
+ def _resolve_api_urls(self, url: str) -> tuple[str, str]:
5775
+ """
5776
+ Resolves the base url and parsed url from the given url.
5777
+ """
5778
+ parsed_url = urlparse(url)
5779
+ scheme = parsed_url.scheme.lower()
5780
+ if scheme not in ("http", "https"):
5781
+ raise ValueError(
5782
+ f"Invalid URL scheme {scheme} for HTTPRunDB, only http(s) is supported"
5568
5783
  )
5569
- page_params.pop("limit")
5570
- return page_params
5784
+
5785
+ endpoint = parsed_url.hostname
5786
+ if parsed_url.port:
5787
+ endpoint += f":{parsed_url.port}"
5788
+ base_url = f"{parsed_url.scheme}://{endpoint}{parsed_url.path}"
5789
+
5790
+ return base_url, parsed_url
5571
5791
 
5572
5792
 
5573
5793
  def _as_json(obj):