mlrun 1.7.0rc5__py3-none-any.whl → 1.7.2__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.
- mlrun/__init__.py +11 -1
- mlrun/__main__.py +39 -121
- mlrun/{datastore/helpers.py → alerts/__init__.py} +2 -5
- mlrun/alerts/alert.py +248 -0
- mlrun/api/schemas/__init__.py +4 -3
- mlrun/artifacts/__init__.py +8 -3
- mlrun/artifacts/base.py +39 -254
- mlrun/artifacts/dataset.py +9 -190
- mlrun/artifacts/manager.py +73 -46
- mlrun/artifacts/model.py +30 -158
- mlrun/artifacts/plots.py +23 -380
- mlrun/common/constants.py +73 -2
- mlrun/common/db/sql_session.py +3 -2
- mlrun/common/formatters/__init__.py +21 -0
- mlrun/common/formatters/artifact.py +46 -0
- mlrun/common/formatters/base.py +113 -0
- mlrun/common/formatters/feature_set.py +44 -0
- mlrun/common/formatters/function.py +46 -0
- mlrun/common/formatters/pipeline.py +53 -0
- mlrun/common/formatters/project.py +51 -0
- mlrun/common/formatters/run.py +29 -0
- mlrun/common/helpers.py +11 -1
- mlrun/{runtimes → common/runtimes}/constants.py +32 -4
- mlrun/common/schemas/__init__.py +21 -4
- mlrun/common/schemas/alert.py +202 -0
- mlrun/common/schemas/api_gateway.py +113 -2
- mlrun/common/schemas/artifact.py +28 -1
- mlrun/common/schemas/auth.py +11 -0
- mlrun/common/schemas/client_spec.py +2 -1
- mlrun/common/schemas/common.py +7 -4
- mlrun/common/schemas/constants.py +3 -0
- mlrun/common/schemas/feature_store.py +58 -28
- mlrun/common/schemas/frontend_spec.py +8 -0
- mlrun/common/schemas/function.py +11 -0
- mlrun/common/schemas/hub.py +7 -9
- mlrun/common/schemas/model_monitoring/__init__.py +21 -4
- mlrun/common/schemas/model_monitoring/constants.py +136 -42
- mlrun/common/schemas/model_monitoring/grafana.py +9 -5
- mlrun/common/schemas/model_monitoring/model_endpoints.py +89 -41
- mlrun/common/schemas/notification.py +69 -12
- mlrun/{runtimes/mpijob/v1alpha1.py → common/schemas/pagination.py} +10 -13
- mlrun/common/schemas/pipeline.py +7 -0
- mlrun/common/schemas/project.py +67 -16
- mlrun/common/schemas/runs.py +17 -0
- mlrun/common/schemas/schedule.py +1 -1
- mlrun/common/schemas/workflow.py +10 -2
- mlrun/common/types.py +14 -1
- mlrun/config.py +224 -58
- mlrun/data_types/data_types.py +11 -1
- mlrun/data_types/spark.py +5 -4
- mlrun/data_types/to_pandas.py +75 -34
- mlrun/datastore/__init__.py +8 -10
- mlrun/datastore/alibaba_oss.py +131 -0
- mlrun/datastore/azure_blob.py +131 -43
- mlrun/datastore/base.py +107 -47
- mlrun/datastore/datastore.py +17 -7
- mlrun/datastore/datastore_profile.py +91 -7
- mlrun/datastore/dbfs_store.py +3 -7
- mlrun/datastore/filestore.py +1 -3
- mlrun/datastore/google_cloud_storage.py +92 -32
- mlrun/datastore/hdfs.py +5 -0
- mlrun/datastore/inmem.py +6 -3
- mlrun/datastore/redis.py +3 -2
- mlrun/datastore/s3.py +30 -12
- mlrun/datastore/snowflake_utils.py +45 -0
- mlrun/datastore/sources.py +274 -59
- mlrun/datastore/spark_utils.py +30 -0
- mlrun/datastore/store_resources.py +9 -7
- mlrun/datastore/storeytargets.py +151 -0
- mlrun/datastore/targets.py +374 -102
- mlrun/datastore/utils.py +68 -5
- mlrun/datastore/v3io.py +28 -50
- mlrun/db/auth_utils.py +152 -0
- mlrun/db/base.py +231 -22
- mlrun/db/factory.py +1 -4
- mlrun/db/httpdb.py +864 -228
- mlrun/db/nopdb.py +268 -16
- mlrun/errors.py +35 -5
- mlrun/execution.py +111 -38
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +46 -53
- mlrun/feature_store/common.py +6 -11
- mlrun/feature_store/feature_set.py +48 -23
- mlrun/feature_store/feature_vector.py +13 -2
- mlrun/feature_store/ingestion.py +7 -6
- mlrun/feature_store/retrieval/base.py +9 -4
- mlrun/feature_store/retrieval/dask_merger.py +2 -0
- mlrun/feature_store/retrieval/job.py +13 -4
- mlrun/feature_store/retrieval/local_merger.py +2 -0
- mlrun/feature_store/retrieval/spark_merger.py +24 -32
- mlrun/feature_store/steps.py +38 -19
- mlrun/features.py +6 -14
- mlrun/frameworks/_common/plan.py +3 -3
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +2 -2
- mlrun/frameworks/lgbm/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
- mlrun/frameworks/lgbm/model_handler.py +1 -1
- mlrun/frameworks/parallel_coordinates.py +4 -4
- mlrun/frameworks/pytorch/__init__.py +2 -2
- mlrun/frameworks/sklearn/__init__.py +1 -1
- mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
- mlrun/frameworks/tf_keras/__init__.py +5 -2
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/mlrun_interface.py +2 -2
- mlrun/frameworks/xgboost/__init__.py +1 -1
- mlrun/k8s_utils.py +57 -12
- mlrun/launcher/__init__.py +1 -1
- mlrun/launcher/base.py +6 -5
- mlrun/launcher/client.py +13 -11
- mlrun/launcher/factory.py +1 -1
- mlrun/launcher/local.py +15 -5
- mlrun/launcher/remote.py +10 -3
- mlrun/lists.py +6 -2
- mlrun/model.py +297 -48
- mlrun/model_monitoring/__init__.py +1 -1
- mlrun/model_monitoring/api.py +152 -357
- mlrun/model_monitoring/applications/__init__.py +10 -0
- mlrun/model_monitoring/applications/_application_steps.py +190 -0
- mlrun/model_monitoring/applications/base.py +108 -0
- mlrun/model_monitoring/applications/context.py +341 -0
- mlrun/model_monitoring/{evidently_application.py → applications/evidently_base.py} +27 -22
- mlrun/model_monitoring/applications/histogram_data_drift.py +227 -91
- mlrun/model_monitoring/applications/results.py +99 -0
- mlrun/model_monitoring/controller.py +130 -303
- mlrun/model_monitoring/{stores/models/sqlite.py → db/__init__.py} +5 -10
- mlrun/model_monitoring/db/stores/__init__.py +136 -0
- mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
- mlrun/model_monitoring/db/stores/base/store.py +213 -0
- mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +190 -0
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +103 -0
- mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +659 -0
- mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +726 -0
- mlrun/model_monitoring/db/tsdb/__init__.py +105 -0
- mlrun/model_monitoring/db/tsdb/base.py +448 -0
- mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
- mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +298 -0
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +42 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +522 -0
- mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +158 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +849 -0
- mlrun/model_monitoring/features_drift_table.py +34 -22
- mlrun/model_monitoring/helpers.py +177 -39
- mlrun/model_monitoring/model_endpoint.py +3 -2
- mlrun/model_monitoring/stream_processing.py +165 -398
- mlrun/model_monitoring/tracking_policy.py +7 -1
- mlrun/model_monitoring/writer.py +161 -125
- mlrun/package/packagers/default_packager.py +2 -2
- mlrun/package/packagers_manager.py +1 -0
- mlrun/package/utils/_formatter.py +2 -2
- mlrun/platforms/__init__.py +11 -10
- mlrun/platforms/iguazio.py +67 -228
- mlrun/projects/__init__.py +6 -1
- mlrun/projects/operations.py +47 -20
- mlrun/projects/pipelines.py +396 -249
- mlrun/projects/project.py +1125 -414
- mlrun/render.py +28 -22
- mlrun/run.py +207 -180
- mlrun/runtimes/__init__.py +76 -11
- mlrun/runtimes/base.py +40 -14
- mlrun/runtimes/daskjob.py +9 -2
- mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
- mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
- mlrun/runtimes/funcdoc.py +1 -29
- mlrun/runtimes/kubejob.py +34 -128
- mlrun/runtimes/local.py +39 -10
- mlrun/runtimes/mpijob/__init__.py +0 -20
- mlrun/runtimes/mpijob/abstract.py +8 -8
- mlrun/runtimes/mpijob/v1.py +1 -1
- mlrun/runtimes/nuclio/api_gateway.py +646 -177
- mlrun/runtimes/nuclio/application/__init__.py +15 -0
- mlrun/runtimes/nuclio/application/application.py +758 -0
- mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
- mlrun/runtimes/nuclio/function.py +188 -68
- mlrun/runtimes/nuclio/serving.py +57 -60
- mlrun/runtimes/pod.py +191 -58
- mlrun/runtimes/remotesparkjob.py +11 -8
- mlrun/runtimes/sparkjob/spark3job.py +17 -18
- mlrun/runtimes/utils.py +40 -73
- mlrun/secrets.py +6 -2
- mlrun/serving/__init__.py +8 -1
- mlrun/serving/remote.py +2 -3
- mlrun/serving/routers.py +89 -64
- mlrun/serving/server.py +54 -26
- mlrun/serving/states.py +187 -56
- mlrun/serving/utils.py +19 -11
- mlrun/serving/v2_serving.py +136 -63
- mlrun/track/tracker.py +2 -1
- mlrun/track/trackers/mlflow_tracker.py +5 -0
- mlrun/utils/async_http.py +26 -6
- mlrun/utils/db.py +18 -0
- mlrun/utils/helpers.py +375 -105
- mlrun/utils/http.py +2 -2
- mlrun/utils/logger.py +75 -9
- mlrun/utils/notifications/notification/__init__.py +14 -10
- mlrun/utils/notifications/notification/base.py +48 -0
- mlrun/utils/notifications/notification/console.py +2 -0
- mlrun/utils/notifications/notification/git.py +24 -1
- mlrun/utils/notifications/notification/ipython.py +2 -0
- mlrun/utils/notifications/notification/slack.py +96 -21
- mlrun/utils/notifications/notification/webhook.py +63 -2
- mlrun/utils/notifications/notification_pusher.py +146 -16
- mlrun/utils/regex.py +9 -0
- mlrun/utils/retryer.py +3 -2
- mlrun/utils/v3io_clients.py +2 -3
- mlrun/utils/version/version.json +2 -2
- mlrun-1.7.2.dist-info/METADATA +390 -0
- mlrun-1.7.2.dist-info/RECORD +351 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/WHEEL +1 -1
- mlrun/feature_store/retrieval/conversion.py +0 -271
- mlrun/kfpops.py +0 -868
- mlrun/model_monitoring/application.py +0 -310
- mlrun/model_monitoring/batch.py +0 -974
- mlrun/model_monitoring/controller_handler.py +0 -37
- mlrun/model_monitoring/prometheus.py +0 -216
- mlrun/model_monitoring/stores/__init__.py +0 -111
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -574
- mlrun/model_monitoring/stores/model_endpoint_store.py +0 -145
- mlrun/model_monitoring/stores/models/__init__.py +0 -27
- mlrun/model_monitoring/stores/models/base.py +0 -84
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -382
- mlrun/platforms/other.py +0 -305
- mlrun-1.7.0rc5.dist-info/METADATA +0 -269
- mlrun-1.7.0rc5.dist-info/RECORD +0 -323
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/top_level.txt +0 -0
mlrun/db/httpdb.py
CHANGED
|
@@ -11,29 +11,37 @@
|
|
|
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
|
+
|
|
14
15
|
import enum
|
|
15
16
|
import http
|
|
16
17
|
import re
|
|
17
|
-
import tempfile
|
|
18
18
|
import time
|
|
19
19
|
import traceback
|
|
20
20
|
import typing
|
|
21
21
|
import warnings
|
|
22
|
+
from copy import deepcopy
|
|
22
23
|
from datetime import datetime, timedelta
|
|
23
24
|
from os import path, remove
|
|
24
25
|
from typing import Optional, Union
|
|
25
26
|
from urllib.parse import urlparse
|
|
26
27
|
|
|
27
|
-
import kfp
|
|
28
28
|
import requests
|
|
29
29
|
import semver
|
|
30
|
+
from mlrun_pipelines.utils import compile_pipeline
|
|
30
31
|
|
|
31
32
|
import mlrun
|
|
33
|
+
import mlrun.common.formatters
|
|
34
|
+
import mlrun.common.runtimes
|
|
32
35
|
import mlrun.common.schemas
|
|
36
|
+
import mlrun.common.types
|
|
33
37
|
import mlrun.model_monitoring.model_endpoint
|
|
34
38
|
import mlrun.platforms
|
|
35
39
|
import mlrun.projects
|
|
36
40
|
import mlrun.runtimes.nuclio.api_gateway
|
|
41
|
+
import mlrun.runtimes.nuclio.function
|
|
42
|
+
import mlrun.utils
|
|
43
|
+
from mlrun.alerts.alert import AlertConfig
|
|
44
|
+
from mlrun.db.auth_utils import OAuthClientIDTokenProvider, StaticTokenProvider
|
|
37
45
|
from mlrun.errors import MLRunInvalidArgumentError, err_to_str
|
|
38
46
|
|
|
39
47
|
from ..artifacts import Artifact
|
|
@@ -46,7 +54,6 @@ from ..utils import (
|
|
|
46
54
|
datetime_to_iso,
|
|
47
55
|
dict_to_json,
|
|
48
56
|
logger,
|
|
49
|
-
new_pipe_metadata,
|
|
50
57
|
normalize_name,
|
|
51
58
|
version,
|
|
52
59
|
)
|
|
@@ -134,17 +141,28 @@ class HTTPRunDB(RunDBInterface):
|
|
|
134
141
|
endpoint += f":{parsed_url.port}"
|
|
135
142
|
base_url = f"{parsed_url.scheme}://{endpoint}{parsed_url.path}"
|
|
136
143
|
|
|
144
|
+
self.base_url = base_url
|
|
137
145
|
username = parsed_url.username or config.httpdb.user
|
|
138
146
|
password = parsed_url.password or config.httpdb.password
|
|
147
|
+
self.token_provider = None
|
|
148
|
+
|
|
149
|
+
if config.auth_with_client_id.enabled:
|
|
150
|
+
self.token_provider = OAuthClientIDTokenProvider(
|
|
151
|
+
token_endpoint=mlrun.get_secret_or_env("MLRUN_AUTH_TOKEN_ENDPOINT"),
|
|
152
|
+
client_id=mlrun.get_secret_or_env("MLRUN_AUTH_CLIENT_ID"),
|
|
153
|
+
client_secret=mlrun.get_secret_or_env("MLRUN_AUTH_CLIENT_SECRET"),
|
|
154
|
+
timeout=config.auth_with_client_id.request_timeout,
|
|
155
|
+
)
|
|
156
|
+
else:
|
|
157
|
+
username, password, token = mlrun.platforms.add_or_refresh_credentials(
|
|
158
|
+
parsed_url.hostname, username, password, config.httpdb.token
|
|
159
|
+
)
|
|
139
160
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
)
|
|
161
|
+
if token:
|
|
162
|
+
self.token_provider = StaticTokenProvider(token)
|
|
143
163
|
|
|
144
|
-
self.base_url = base_url
|
|
145
164
|
self.user = username
|
|
146
165
|
self.password = password
|
|
147
|
-
self.token = token
|
|
148
166
|
|
|
149
167
|
def __repr__(self):
|
|
150
168
|
cls = self.__class__.__name__
|
|
@@ -180,7 +198,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
180
198
|
headers=None,
|
|
181
199
|
timeout=45,
|
|
182
200
|
version=None,
|
|
183
|
-
):
|
|
201
|
+
) -> requests.Response:
|
|
184
202
|
"""Perform a direct REST API call on the :py:mod:`mlrun` API server.
|
|
185
203
|
|
|
186
204
|
Caution:
|
|
@@ -198,7 +216,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
198
216
|
:param version: API version to use, None (the default) will mean to use the default value from config,
|
|
199
217
|
for un-versioned api set an empty string.
|
|
200
218
|
|
|
201
|
-
:
|
|
219
|
+
:returns: `requests.Response` HTTP response object
|
|
202
220
|
"""
|
|
203
221
|
url = self.get_base_api_url(path, version)
|
|
204
222
|
kw = {
|
|
@@ -214,17 +232,19 @@ class HTTPRunDB(RunDBInterface):
|
|
|
214
232
|
|
|
215
233
|
if self.user:
|
|
216
234
|
kw["auth"] = (self.user, self.password)
|
|
217
|
-
elif self.
|
|
218
|
-
|
|
219
|
-
if
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
"
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
235
|
+
elif self.token_provider:
|
|
236
|
+
token = self.token_provider.get_token()
|
|
237
|
+
if token:
|
|
238
|
+
# Iguazio auth doesn't support passing token through bearer, so use cookie instead
|
|
239
|
+
if self.token_provider.is_iguazio_session():
|
|
240
|
+
session_cookie = f'j:{{"sid": "{token}"}}'
|
|
241
|
+
cookies = {
|
|
242
|
+
"session": session_cookie,
|
|
243
|
+
}
|
|
244
|
+
kw["cookies"] = cookies
|
|
245
|
+
else:
|
|
246
|
+
if "Authorization" not in kw.setdefault("headers", {}):
|
|
247
|
+
kw["headers"].update({"Authorization": "Bearer " + token})
|
|
228
248
|
|
|
229
249
|
if mlrun.common.schemas.HeaderNames.client_version not in kw.setdefault(
|
|
230
250
|
"headers", {}
|
|
@@ -279,6 +299,68 @@ class HTTPRunDB(RunDBInterface):
|
|
|
279
299
|
|
|
280
300
|
return response
|
|
281
301
|
|
|
302
|
+
def paginated_api_call(
|
|
303
|
+
self,
|
|
304
|
+
method,
|
|
305
|
+
path,
|
|
306
|
+
error=None,
|
|
307
|
+
params=None,
|
|
308
|
+
body=None,
|
|
309
|
+
json=None,
|
|
310
|
+
headers=None,
|
|
311
|
+
timeout=45,
|
|
312
|
+
version=None,
|
|
313
|
+
) -> typing.Generator[requests.Response, None, None]:
|
|
314
|
+
"""
|
|
315
|
+
Calls the api with pagination, yielding each page of the response
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
def _api_call(_params):
|
|
319
|
+
return self.api_call(
|
|
320
|
+
method=method,
|
|
321
|
+
path=path,
|
|
322
|
+
error=error,
|
|
323
|
+
params=_params,
|
|
324
|
+
body=body,
|
|
325
|
+
json=json,
|
|
326
|
+
headers=headers,
|
|
327
|
+
timeout=timeout,
|
|
328
|
+
version=version,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
first_page_params = deepcopy(params) or {}
|
|
332
|
+
first_page_params["page"] = 1
|
|
333
|
+
first_page_params["page-size"] = config.httpdb.pagination.default_page_size
|
|
334
|
+
response = _api_call(first_page_params)
|
|
335
|
+
page_token = response.json().get("pagination", {}).get("page-token")
|
|
336
|
+
if not page_token:
|
|
337
|
+
yield response
|
|
338
|
+
return
|
|
339
|
+
|
|
340
|
+
params_with_page_token = deepcopy(params) or {}
|
|
341
|
+
params_with_page_token["page-token"] = page_token
|
|
342
|
+
while page_token:
|
|
343
|
+
yield response
|
|
344
|
+
try:
|
|
345
|
+
response = _api_call(params_with_page_token)
|
|
346
|
+
except mlrun.errors.MLRunNotFoundError:
|
|
347
|
+
# pagination token expired
|
|
348
|
+
break
|
|
349
|
+
|
|
350
|
+
page_token = response.json().get("pagination", {}).get("page-token", None)
|
|
351
|
+
|
|
352
|
+
@staticmethod
|
|
353
|
+
def process_paginated_responses(
|
|
354
|
+
responses: typing.Generator[requests.Response, None, None], key: str = "data"
|
|
355
|
+
) -> list[typing.Any]:
|
|
356
|
+
"""
|
|
357
|
+
Processes the paginated responses and returns the combined data
|
|
358
|
+
"""
|
|
359
|
+
data = []
|
|
360
|
+
for response in responses:
|
|
361
|
+
data.extend(response.json().get(key, []))
|
|
362
|
+
return data
|
|
363
|
+
|
|
282
364
|
def _init_session(self, retry_on_post: bool = False):
|
|
283
365
|
return mlrun.utils.HTTPSessionWithRetry(
|
|
284
366
|
retry_on_exception=config.httpdb.retry_api_call_on_exception
|
|
@@ -311,7 +393,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
311
393
|
|
|
312
394
|
For example::
|
|
313
395
|
|
|
314
|
-
config.dbpath = config.dbpath or
|
|
396
|
+
config.dbpath = config.dbpath or "http://mlrun-api:8080"
|
|
315
397
|
db = get_run_db().connect()
|
|
316
398
|
"""
|
|
317
399
|
# hack to allow unit tests to instantiate HTTPRunDB without a real server behind
|
|
@@ -443,14 +525,18 @@ class HTTPRunDB(RunDBInterface):
|
|
|
443
525
|
server_cfg.get("external_platform_tracking")
|
|
444
526
|
or config.external_platform_tracking
|
|
445
527
|
)
|
|
446
|
-
config.model_endpoint_monitoring.store_type = (
|
|
447
|
-
server_cfg.get("model_endpoint_monitoring_store_type")
|
|
448
|
-
or config.model_endpoint_monitoring.store_type
|
|
449
|
-
)
|
|
450
528
|
config.model_endpoint_monitoring.endpoint_store_connection = (
|
|
451
529
|
server_cfg.get("model_endpoint_monitoring_endpoint_store_connection")
|
|
452
530
|
or config.model_endpoint_monitoring.endpoint_store_connection
|
|
453
531
|
)
|
|
532
|
+
config.model_endpoint_monitoring.tsdb_connection = (
|
|
533
|
+
server_cfg.get("model_monitoring_tsdb_connection")
|
|
534
|
+
or config.model_endpoint_monitoring.tsdb_connection
|
|
535
|
+
)
|
|
536
|
+
config.model_endpoint_monitoring.stream_connection = (
|
|
537
|
+
server_cfg.get("stream_connection")
|
|
538
|
+
or config.model_endpoint_monitoring.stream_connection
|
|
539
|
+
)
|
|
454
540
|
config.packagers = server_cfg.get("packagers") or config.packagers
|
|
455
541
|
server_data_prefixes = server_cfg.get("feature_store_data_prefixes") or {}
|
|
456
542
|
for prefix in ["default", "nosql", "redisnosql"]:
|
|
@@ -463,6 +549,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
463
549
|
server_cfg.get("feature_store_default_targets")
|
|
464
550
|
or config.feature_store.default_targets
|
|
465
551
|
)
|
|
552
|
+
config.alerts.mode = server_cfg.get("alerts_mode") or config.alerts.mode
|
|
466
553
|
|
|
467
554
|
except Exception as exc:
|
|
468
555
|
logger.warning(
|
|
@@ -509,7 +596,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
509
596
|
if offset < 0:
|
|
510
597
|
raise MLRunInvalidArgumentError("Offset cannot be negative")
|
|
511
598
|
if size is None:
|
|
512
|
-
size = int(
|
|
599
|
+
size = int(mlrun.mlconf.httpdb.logs.pull_logs_default_size_limit)
|
|
513
600
|
elif size == -1:
|
|
514
601
|
logger.warning(
|
|
515
602
|
"Retrieving all logs. This may be inefficient and can result in a large log."
|
|
@@ -555,33 +642,35 @@ class HTTPRunDB(RunDBInterface):
|
|
|
555
642
|
|
|
556
643
|
state, text = self.get_log(uid, project, offset=offset)
|
|
557
644
|
if text:
|
|
558
|
-
print(text.decode(errors=
|
|
645
|
+
print(text.decode(errors=mlrun.mlconf.httpdb.logs.decode.errors))
|
|
559
646
|
nil_resp = 0
|
|
560
647
|
while True:
|
|
561
648
|
offset += len(text)
|
|
562
649
|
# if we get 3 nil responses in a row, increase the sleep time to 10 seconds
|
|
563
650
|
# TODO: refactor this to use a conditional backoff mechanism
|
|
564
651
|
if nil_resp < 3:
|
|
565
|
-
time.sleep(int(
|
|
652
|
+
time.sleep(int(mlrun.mlconf.httpdb.logs.pull_logs_default_interval))
|
|
566
653
|
else:
|
|
567
654
|
time.sleep(
|
|
568
|
-
int(
|
|
655
|
+
int(
|
|
656
|
+
mlrun.mlconf.httpdb.logs.pull_logs_backoff_no_logs_default_interval
|
|
657
|
+
)
|
|
569
658
|
)
|
|
570
659
|
state, text = self.get_log(uid, project, offset=offset)
|
|
571
660
|
if text:
|
|
572
661
|
nil_resp = 0
|
|
573
662
|
print(
|
|
574
|
-
text.decode(errors=
|
|
663
|
+
text.decode(errors=mlrun.mlconf.httpdb.logs.decode.errors),
|
|
575
664
|
end="",
|
|
576
665
|
)
|
|
577
666
|
else:
|
|
578
667
|
nil_resp += 1
|
|
579
668
|
|
|
580
669
|
if watch and state in [
|
|
581
|
-
mlrun.runtimes.constants.RunStates.pending,
|
|
582
|
-
mlrun.runtimes.constants.RunStates.running,
|
|
583
|
-
mlrun.runtimes.constants.RunStates.created,
|
|
584
|
-
mlrun.runtimes.constants.RunStates.aborting,
|
|
670
|
+
mlrun.common.runtimes.constants.RunStates.pending,
|
|
671
|
+
mlrun.common.runtimes.constants.RunStates.running,
|
|
672
|
+
mlrun.common.runtimes.constants.RunStates.created,
|
|
673
|
+
mlrun.common.runtimes.constants.RunStates.aborting,
|
|
585
674
|
]:
|
|
586
675
|
continue
|
|
587
676
|
else:
|
|
@@ -637,16 +726,26 @@ class HTTPRunDB(RunDBInterface):
|
|
|
637
726
|
)
|
|
638
727
|
return None
|
|
639
728
|
|
|
640
|
-
def read_run(
|
|
729
|
+
def read_run(
|
|
730
|
+
self,
|
|
731
|
+
uid,
|
|
732
|
+
project="",
|
|
733
|
+
iter=0,
|
|
734
|
+
format_: mlrun.common.formatters.RunFormat = mlrun.common.formatters.RunFormat.full,
|
|
735
|
+
):
|
|
641
736
|
"""Read the details of a stored run from the DB.
|
|
642
737
|
|
|
643
|
-
:param uid:
|
|
644
|
-
:param project:
|
|
645
|
-
:param iter:
|
|
738
|
+
:param uid: The run's unique ID.
|
|
739
|
+
:param project: Project name.
|
|
740
|
+
:param iter: Iteration within a specific execution.
|
|
741
|
+
:param format_: The format in which to return the run details.
|
|
646
742
|
"""
|
|
647
743
|
|
|
648
744
|
path = self._path_of("runs", project, uid)
|
|
649
|
-
params = {
|
|
745
|
+
params = {
|
|
746
|
+
"iter": iter,
|
|
747
|
+
"format": format_.value,
|
|
748
|
+
}
|
|
650
749
|
error = f"get run {project}/{uid}"
|
|
651
750
|
resp = self.api_call("GET", path, error, params=params)
|
|
652
751
|
return resp.json()["data"]
|
|
@@ -670,7 +769,10 @@ class HTTPRunDB(RunDBInterface):
|
|
|
670
769
|
uid: Optional[Union[str, list[str]]] = None,
|
|
671
770
|
project: Optional[str] = None,
|
|
672
771
|
labels: Optional[Union[str, list[str]]] = None,
|
|
673
|
-
state: Optional[
|
|
772
|
+
state: Optional[
|
|
773
|
+
mlrun.common.runtimes.constants.RunStates
|
|
774
|
+
] = None, # Backward compatibility
|
|
775
|
+
states: typing.Optional[list[mlrun.common.runtimes.constants.RunStates]] = None,
|
|
674
776
|
sort: bool = True,
|
|
675
777
|
last: int = 0,
|
|
676
778
|
iter: bool = False,
|
|
@@ -695,9 +797,11 @@ class HTTPRunDB(RunDBInterface):
|
|
|
695
797
|
|
|
696
798
|
Example::
|
|
697
799
|
|
|
698
|
-
runs = db.list_runs(
|
|
800
|
+
runs = db.list_runs(
|
|
801
|
+
name="download", project="iris", labels=["owner=admin", "kind=job"]
|
|
802
|
+
)
|
|
699
803
|
# If running in Jupyter, can use the .show() function to display the results
|
|
700
|
-
db.list_runs(name=
|
|
804
|
+
db.list_runs(name="", project=project_name).show()
|
|
701
805
|
|
|
702
806
|
|
|
703
807
|
:param name: Name of the run to retrieve.
|
|
@@ -706,7 +810,8 @@ class HTTPRunDB(RunDBInterface):
|
|
|
706
810
|
:param labels: A list of labels to filter by. Label filters work by either filtering a specific value
|
|
707
811
|
of a label (i.e. list("key=value")) or by looking for the existence of a given
|
|
708
812
|
key (i.e. "key").
|
|
709
|
-
:param state: List only runs whose state is specified.
|
|
813
|
+
:param state: Deprecated - List only runs whose state is specified (will be removed in 1.9.0)
|
|
814
|
+
:param states: List only runs whose state is one of the provided states.
|
|
710
815
|
:param sort: Whether to sort the result according to their start time. Otherwise, results will be
|
|
711
816
|
returned by their internal order in the DB (order will not be guaranteed).
|
|
712
817
|
:param last: Deprecated - currently not used (will be removed in 1.8.0).
|
|
@@ -742,11 +847,19 @@ class HTTPRunDB(RunDBInterface):
|
|
|
742
847
|
FutureWarning,
|
|
743
848
|
)
|
|
744
849
|
|
|
850
|
+
if state:
|
|
851
|
+
# TODO: Remove this in 1.9.0
|
|
852
|
+
warnings.warn(
|
|
853
|
+
"'state' is deprecated and will be removed in 1.9.0. Use 'states' instead.",
|
|
854
|
+
FutureWarning,
|
|
855
|
+
)
|
|
856
|
+
|
|
745
857
|
if (
|
|
746
858
|
not name
|
|
747
859
|
and not uid
|
|
748
860
|
and not labels
|
|
749
861
|
and not state
|
|
862
|
+
and not states
|
|
750
863
|
and not last
|
|
751
864
|
and not start_time_from
|
|
752
865
|
and not start_time_to
|
|
@@ -758,14 +871,16 @@ class HTTPRunDB(RunDBInterface):
|
|
|
758
871
|
):
|
|
759
872
|
# default to last week on no filter
|
|
760
873
|
start_time_from = datetime.now() - timedelta(days=7)
|
|
761
|
-
partition_by = mlrun.common.schemas.RunPartitionByField.
|
|
874
|
+
partition_by = mlrun.common.schemas.RunPartitionByField.project_and_name
|
|
762
875
|
partition_sort_by = mlrun.common.schemas.SortField.updated
|
|
763
876
|
|
|
764
877
|
params = {
|
|
765
878
|
"name": name,
|
|
766
879
|
"uid": uid,
|
|
767
880
|
"label": labels or [],
|
|
768
|
-
"state": state
|
|
881
|
+
"state": mlrun.utils.helpers.as_list(state)
|
|
882
|
+
if state is not None
|
|
883
|
+
else states or None,
|
|
769
884
|
"sort": bool2str(sort),
|
|
770
885
|
"iter": bool2str(iter),
|
|
771
886
|
"start_time_from": datetime_to_iso(start_time_from),
|
|
@@ -788,15 +903,15 @@ class HTTPRunDB(RunDBInterface):
|
|
|
788
903
|
)
|
|
789
904
|
error = "list runs"
|
|
790
905
|
_path = self._path_of("runs", project)
|
|
791
|
-
|
|
792
|
-
return RunList(
|
|
906
|
+
responses = self.paginated_api_call("GET", _path, error, params=params)
|
|
907
|
+
return RunList(self.process_paginated_responses(responses, "runs"))
|
|
793
908
|
|
|
794
909
|
def del_runs(self, name=None, project=None, labels=None, state=None, days_ago=0):
|
|
795
910
|
"""Delete a group of runs identified by the parameters of the function.
|
|
796
911
|
|
|
797
912
|
Example::
|
|
798
913
|
|
|
799
|
-
db.del_runs(state=
|
|
914
|
+
db.del_runs(state="completed")
|
|
800
915
|
|
|
801
916
|
:param name: Name of the task which the runs belong to.
|
|
802
917
|
:param project: Project to which the runs belong.
|
|
@@ -849,7 +964,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
849
964
|
|
|
850
965
|
# we do this because previously the 'uid' name was used for the 'tree' parameter
|
|
851
966
|
tree = tree or uid
|
|
852
|
-
|
|
967
|
+
project = project or mlrun.mlconf.default_project
|
|
853
968
|
endpoint_path = f"projects/{project}/artifacts/{key}"
|
|
854
969
|
|
|
855
970
|
error = f"store artifact {project}/{key}"
|
|
@@ -875,6 +990,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
875
990
|
project="",
|
|
876
991
|
tree=None,
|
|
877
992
|
uid=None,
|
|
993
|
+
format_: mlrun.common.formatters.ArtifactFormat = mlrun.common.formatters.ArtifactFormat.full,
|
|
878
994
|
):
|
|
879
995
|
"""Read an artifact, identified by its key, tag, tree and iteration.
|
|
880
996
|
|
|
@@ -884,25 +1000,37 @@ class HTTPRunDB(RunDBInterface):
|
|
|
884
1000
|
:param project: Project that the artifact belongs to.
|
|
885
1001
|
:param tree: The tree which generated this artifact.
|
|
886
1002
|
:param uid: A unique ID for this specific version of the artifact (the uid that was generated in the backend)
|
|
1003
|
+
:param format_: The format in which to return the artifact. Default is 'full'.
|
|
887
1004
|
"""
|
|
888
1005
|
|
|
889
|
-
project = project or
|
|
1006
|
+
project = project or mlrun.mlconf.default_project
|
|
890
1007
|
tag = tag or "latest"
|
|
891
1008
|
endpoint_path = f"projects/{project}/artifacts/{key}"
|
|
892
1009
|
error = f"read artifact {project}/{key}"
|
|
893
|
-
# explicitly set artifacts format to 'full' since old servers may default to 'legacy'
|
|
894
1010
|
params = {
|
|
895
|
-
"format":
|
|
1011
|
+
"format": format_,
|
|
896
1012
|
"tag": tag,
|
|
897
1013
|
"tree": tree,
|
|
898
|
-
"uid": uid,
|
|
1014
|
+
"object-uid": uid,
|
|
899
1015
|
}
|
|
900
|
-
if iter:
|
|
1016
|
+
if iter is not None:
|
|
901
1017
|
params["iter"] = str(iter)
|
|
902
1018
|
resp = self.api_call("GET", endpoint_path, error, params=params, version="v2")
|
|
903
1019
|
return resp.json()
|
|
904
1020
|
|
|
905
|
-
def del_artifact(
|
|
1021
|
+
def del_artifact(
|
|
1022
|
+
self,
|
|
1023
|
+
key,
|
|
1024
|
+
tag=None,
|
|
1025
|
+
project="",
|
|
1026
|
+
tree=None,
|
|
1027
|
+
uid=None,
|
|
1028
|
+
deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
|
|
1029
|
+
mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
|
|
1030
|
+
),
|
|
1031
|
+
secrets: dict = None,
|
|
1032
|
+
iter=None,
|
|
1033
|
+
):
|
|
906
1034
|
"""Delete an artifact.
|
|
907
1035
|
|
|
908
1036
|
:param key: Identifying key of the artifact.
|
|
@@ -910,17 +1038,28 @@ class HTTPRunDB(RunDBInterface):
|
|
|
910
1038
|
:param project: Project that the artifact belongs to.
|
|
911
1039
|
:param tree: The tree which generated this artifact.
|
|
912
1040
|
:param uid: A unique ID for this specific version of the artifact (the uid that was generated in the backend)
|
|
1041
|
+
:param deletion_strategy: The artifact deletion strategy types.
|
|
1042
|
+
:param secrets: Credentials needed to access the artifact data.
|
|
913
1043
|
"""
|
|
914
|
-
|
|
1044
|
+
project = project or mlrun.mlconf.default_project
|
|
915
1045
|
endpoint_path = f"projects/{project}/artifacts/{key}"
|
|
916
1046
|
params = {
|
|
917
1047
|
"key": key,
|
|
918
1048
|
"tag": tag,
|
|
919
1049
|
"tree": tree,
|
|
920
|
-
"uid": uid,
|
|
1050
|
+
"object-uid": uid,
|
|
1051
|
+
"iter": iter,
|
|
1052
|
+
"deletion_strategy": deletion_strategy,
|
|
921
1053
|
}
|
|
922
1054
|
error = f"del artifact {project}/{key}"
|
|
923
|
-
self.api_call(
|
|
1055
|
+
self.api_call(
|
|
1056
|
+
"DELETE",
|
|
1057
|
+
endpoint_path,
|
|
1058
|
+
error,
|
|
1059
|
+
params=params,
|
|
1060
|
+
version="v2",
|
|
1061
|
+
body=dict_to_json(secrets),
|
|
1062
|
+
)
|
|
924
1063
|
|
|
925
1064
|
def list_artifacts(
|
|
926
1065
|
self,
|
|
@@ -928,24 +1067,31 @@ class HTTPRunDB(RunDBInterface):
|
|
|
928
1067
|
project=None,
|
|
929
1068
|
tag=None,
|
|
930
1069
|
labels: Optional[Union[dict[str, str], list[str]]] = None,
|
|
931
|
-
since=None,
|
|
932
|
-
until=None,
|
|
1070
|
+
since: Optional[datetime] = None,
|
|
1071
|
+
until: Optional[datetime] = None,
|
|
933
1072
|
iter: int = None,
|
|
934
1073
|
best_iteration: bool = False,
|
|
935
1074
|
kind: str = None,
|
|
936
1075
|
category: Union[str, mlrun.common.schemas.ArtifactCategories] = None,
|
|
937
1076
|
tree: str = None,
|
|
1077
|
+
producer_uri: str = None,
|
|
1078
|
+
format_: Optional[
|
|
1079
|
+
mlrun.common.formatters.ArtifactFormat
|
|
1080
|
+
] = mlrun.common.formatters.ArtifactFormat.full,
|
|
1081
|
+
limit: int = None,
|
|
938
1082
|
) -> ArtifactList:
|
|
939
1083
|
"""List artifacts filtered by various parameters.
|
|
940
1084
|
|
|
941
1085
|
Examples::
|
|
942
1086
|
|
|
943
1087
|
# Show latest version of all artifacts in project
|
|
944
|
-
latest_artifacts = db.list_artifacts(
|
|
1088
|
+
latest_artifacts = db.list_artifacts("", tag="latest", project="iris")
|
|
945
1089
|
# check different artifact versions for a specific artifact
|
|
946
|
-
result_versions = db.list_artifacts(
|
|
1090
|
+
result_versions = db.list_artifacts("results", tag="*", project="iris")
|
|
947
1091
|
# Show artifacts with label filters - both uploaded and of binary type
|
|
948
|
-
result_labels = db.list_artifacts(
|
|
1092
|
+
result_labels = db.list_artifacts(
|
|
1093
|
+
"results", tag="*", project="iris", labels=["uploaded", "type=binary"]
|
|
1094
|
+
)
|
|
949
1095
|
|
|
950
1096
|
:param name: Name of artifacts to retrieve. Name with '~' prefix is used as a like query, and is not
|
|
951
1097
|
case-sensitive. This means that querying for ``~name`` may return artifacts named
|
|
@@ -954,16 +1100,21 @@ class HTTPRunDB(RunDBInterface):
|
|
|
954
1100
|
:param tag: Return artifacts assigned this tag.
|
|
955
1101
|
:param labels: Return artifacts that have these labels. Labels can either be a dictionary {"label": "value"} or
|
|
956
1102
|
a list of "label=value" (match label key and value) or "label" (match just label key) strings.
|
|
957
|
-
:param since:
|
|
958
|
-
:param until:
|
|
1103
|
+
:param since: Return artifacts updated after this date (as datetime object).
|
|
1104
|
+
:param until: Return artifacts updated before this date (as datetime object).
|
|
959
1105
|
:param iter: Return artifacts from a specific iteration (where ``iter=0`` means the root iteration). If
|
|
960
1106
|
``None`` (default) return artifacts from all iterations.
|
|
961
1107
|
:param best_iteration: Returns the artifact which belongs to the best iteration of a given run, in the case of
|
|
962
1108
|
artifacts generated from a hyper-param run. If only a single iteration exists, will return the artifact
|
|
963
1109
|
from that iteration. If using ``best_iter``, the ``iter`` parameter must not be used.
|
|
964
|
-
:param kind:
|
|
965
|
-
:param category:
|
|
966
|
-
:param tree:
|
|
1110
|
+
:param kind: Return artifacts of the requested kind.
|
|
1111
|
+
:param category: Return artifacts of the requested category.
|
|
1112
|
+
:param tree: Return artifacts of the requested tree.
|
|
1113
|
+
:param producer_uri: Return artifacts produced by the requested producer URI. Producer URI usually
|
|
1114
|
+
points to a run and is used to filter artifacts by the run that produced them when the artifact producer id
|
|
1115
|
+
is a workflow id (artifact was created as part of a workflow).
|
|
1116
|
+
:param format_: The format in which to return the artifacts. Default is 'full'.
|
|
1117
|
+
:param limit: Maximum number of artifacts to return.
|
|
967
1118
|
"""
|
|
968
1119
|
|
|
969
1120
|
project = project or config.default_project
|
|
@@ -981,7 +1132,11 @@ class HTTPRunDB(RunDBInterface):
|
|
|
981
1132
|
"kind": kind,
|
|
982
1133
|
"category": category,
|
|
983
1134
|
"tree": tree,
|
|
984
|
-
"format":
|
|
1135
|
+
"format": format_,
|
|
1136
|
+
"producer_uri": producer_uri,
|
|
1137
|
+
"limit": limit,
|
|
1138
|
+
"since": datetime_to_iso(since),
|
|
1139
|
+
"until": datetime_to_iso(until),
|
|
985
1140
|
}
|
|
986
1141
|
error = "list artifacts"
|
|
987
1142
|
endpoint_path = f"projects/{project}/artifacts"
|
|
@@ -1071,15 +1226,44 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1071
1226
|
project = project or config.default_project
|
|
1072
1227
|
path = f"projects/{project}/functions/{name}"
|
|
1073
1228
|
error_message = f"Failed deleting function {project}/{name}"
|
|
1074
|
-
self.api_call("DELETE", path, error_message)
|
|
1229
|
+
response = self.api_call("DELETE", path, error_message, version="v2")
|
|
1230
|
+
if response.status_code == http.HTTPStatus.ACCEPTED:
|
|
1231
|
+
logger.info(
|
|
1232
|
+
"Function is being deleted", project_name=project, function_name=name
|
|
1233
|
+
)
|
|
1234
|
+
background_task = mlrun.common.schemas.BackgroundTask(**response.json())
|
|
1235
|
+
background_task = self._wait_for_background_task_to_reach_terminal_state(
|
|
1236
|
+
background_task.metadata.name, project=project
|
|
1237
|
+
)
|
|
1238
|
+
if (
|
|
1239
|
+
background_task.status.state
|
|
1240
|
+
== mlrun.common.schemas.BackgroundTaskState.succeeded
|
|
1241
|
+
):
|
|
1242
|
+
logger.info(
|
|
1243
|
+
"Function deleted", project_name=project, function_name=name
|
|
1244
|
+
)
|
|
1245
|
+
elif (
|
|
1246
|
+
background_task.status.state
|
|
1247
|
+
== mlrun.common.schemas.BackgroundTaskState.failed
|
|
1248
|
+
):
|
|
1249
|
+
logger.info(
|
|
1250
|
+
"Function deletion failed",
|
|
1251
|
+
reason=background_task.status.error,
|
|
1252
|
+
project_name=project,
|
|
1253
|
+
function_name=name,
|
|
1254
|
+
)
|
|
1075
1255
|
|
|
1076
|
-
def list_functions(
|
|
1256
|
+
def list_functions(
|
|
1257
|
+
self, name=None, project=None, tag=None, labels=None, since=None, until=None
|
|
1258
|
+
):
|
|
1077
1259
|
"""Retrieve a list of functions, filtered by specific criteria.
|
|
1078
1260
|
|
|
1079
1261
|
:param name: Return only functions with a specific name.
|
|
1080
1262
|
:param project: Return functions belonging to this project. If not specified, the default project is used.
|
|
1081
|
-
:param tag: Return function versions with specific tags.
|
|
1263
|
+
:param tag: Return function versions with specific tags. To return only tagged functions, set tag to ``"*"``.
|
|
1082
1264
|
:param labels: Return functions that have specific labels assigned to them.
|
|
1265
|
+
:param since: Return functions updated after this date (as datetime object).
|
|
1266
|
+
:param until: Return functions updated before this date (as datetime object).
|
|
1083
1267
|
:returns: List of function objects (as dictionary).
|
|
1084
1268
|
"""
|
|
1085
1269
|
project = project or config.default_project
|
|
@@ -1087,11 +1271,13 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1087
1271
|
"name": name,
|
|
1088
1272
|
"tag": tag,
|
|
1089
1273
|
"label": labels or [],
|
|
1274
|
+
"since": datetime_to_iso(since),
|
|
1275
|
+
"until": datetime_to_iso(until),
|
|
1090
1276
|
}
|
|
1091
1277
|
error = "list functions"
|
|
1092
1278
|
path = f"projects/{project}/functions"
|
|
1093
|
-
|
|
1094
|
-
return
|
|
1279
|
+
responses = self.paginated_api_call("GET", path, error, params=params)
|
|
1280
|
+
return self.process_paginated_responses(responses, "funcs")
|
|
1095
1281
|
|
|
1096
1282
|
def list_runtime_resources(
|
|
1097
1283
|
self,
|
|
@@ -1181,25 +1367,19 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1181
1367
|
period didn't pass.
|
|
1182
1368
|
:param grace_period: Grace period given to the runtime resource before they are actually removed, counted from
|
|
1183
1369
|
the moment they moved to terminal state
|
|
1184
|
-
(defaults to mlrun.
|
|
1370
|
+
(defaults to mlrun.mlconf.runtime_resources_deletion_grace_period).
|
|
1185
1371
|
|
|
1186
1372
|
:returns: :py:class:`~mlrun.common.schemas.GroupedByProjectRuntimeResourcesOutput` listing the runtime resources
|
|
1187
1373
|
that were removed.
|
|
1188
1374
|
"""
|
|
1189
|
-
if grace_period is None:
|
|
1190
|
-
grace_period = config.runtime_resources_deletion_grace_period
|
|
1191
|
-
logger.info(
|
|
1192
|
-
"Using default grace period for runtime resources deletion",
|
|
1193
|
-
grace_period=grace_period,
|
|
1194
|
-
)
|
|
1195
|
-
|
|
1196
1375
|
params = {
|
|
1197
1376
|
"label-selector": label_selector,
|
|
1198
1377
|
"kind": kind,
|
|
1199
1378
|
"object-id": object_id,
|
|
1200
1379
|
"force": force,
|
|
1201
|
-
"grace-period": grace_period,
|
|
1202
1380
|
}
|
|
1381
|
+
if grace_period is not None:
|
|
1382
|
+
params["grace-period"] = grace_period
|
|
1203
1383
|
error = "Failed deleting runtime resources"
|
|
1204
1384
|
project_path = project if project else "*"
|
|
1205
1385
|
response = self.api_call(
|
|
@@ -1237,7 +1417,9 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1237
1417
|
name="run_func_on_tuesdays",
|
|
1238
1418
|
kind="job",
|
|
1239
1419
|
scheduled_object=get_data_func,
|
|
1240
|
-
cron_trigger=schemas.ScheduleCronTrigger(
|
|
1420
|
+
cron_trigger=schemas.ScheduleCronTrigger(
|
|
1421
|
+
day_of_week="tue", hour=15, minute=30
|
|
1422
|
+
),
|
|
1241
1423
|
)
|
|
1242
1424
|
db.create_schedule(project_name, schedule)
|
|
1243
1425
|
"""
|
|
@@ -1340,21 +1522,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1340
1522
|
:param builder_env: Kaniko builder pod env vars dict (for config/credentials)
|
|
1341
1523
|
:param force_build: Force building the image, even when no changes were made
|
|
1342
1524
|
"""
|
|
1343
|
-
|
|
1344
|
-
"s3://"
|
|
1345
|
-
)
|
|
1346
|
-
is_ecr_image = mlrun.utils.is_ecr_url(config.httpdb.builder.docker_registry)
|
|
1347
|
-
if not func.spec.build.load_source_on_run and is_s3_source and is_ecr_image:
|
|
1348
|
-
logger.warning(
|
|
1349
|
-
"Building a function image to ECR and loading an S3 source to the image may require conflicting access "
|
|
1350
|
-
"keys. Only the permissions granted to the platform's configured secret will take affect "
|
|
1351
|
-
"(see mlrun.config.config.httpdb.builder.docker_registry_secret). "
|
|
1352
|
-
"In case the permissions are limited to ECR scope, you may use pull_at_runtime=True instead",
|
|
1353
|
-
source=func.spec.build.source,
|
|
1354
|
-
load_source_on_run=func.spec.build.load_source_on_run,
|
|
1355
|
-
default_docker_registry=config.httpdb.builder.docker_registry,
|
|
1356
|
-
)
|
|
1357
|
-
|
|
1525
|
+
self.warn_on_s3_and_ecr_permissions_conflict(func)
|
|
1358
1526
|
try:
|
|
1359
1527
|
req = {
|
|
1360
1528
|
"function": func.to_dict(),
|
|
@@ -1373,10 +1541,94 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1373
1541
|
|
|
1374
1542
|
if not resp.ok:
|
|
1375
1543
|
logger.error(f"bad resp!!\n{resp.text}")
|
|
1376
|
-
raise ValueError("bad
|
|
1544
|
+
raise ValueError("bad submit build response")
|
|
1377
1545
|
|
|
1378
1546
|
return resp.json()
|
|
1379
1547
|
|
|
1548
|
+
def deploy_nuclio_function(
|
|
1549
|
+
self,
|
|
1550
|
+
func: mlrun.runtimes.RemoteRuntime,
|
|
1551
|
+
builder_env: Optional[dict] = None,
|
|
1552
|
+
):
|
|
1553
|
+
"""
|
|
1554
|
+
Deploy a Nuclio function.
|
|
1555
|
+
|
|
1556
|
+
:param func: Function to build.
|
|
1557
|
+
:param builder_env: Kaniko builder pod env vars dict (for config/credentials)
|
|
1558
|
+
"""
|
|
1559
|
+
func.metadata.project = func.metadata.project or config.default_project
|
|
1560
|
+
self.warn_on_s3_and_ecr_permissions_conflict(func)
|
|
1561
|
+
try:
|
|
1562
|
+
req = {
|
|
1563
|
+
"function": func.to_dict(),
|
|
1564
|
+
}
|
|
1565
|
+
if builder_env:
|
|
1566
|
+
req["builder_env"] = builder_env
|
|
1567
|
+
_path = (
|
|
1568
|
+
f"projects/{func.metadata.project}/nuclio/{func.metadata.name}/deploy"
|
|
1569
|
+
)
|
|
1570
|
+
resp = self.api_call("POST", _path, json=req)
|
|
1571
|
+
except OSError as err:
|
|
1572
|
+
logger.error(f"error submitting nuclio deploy task: {err_to_str(err)}")
|
|
1573
|
+
raise OSError(f"error: cannot submit deploy, {err_to_str(err)}")
|
|
1574
|
+
|
|
1575
|
+
if not resp.ok:
|
|
1576
|
+
logger.error(f"deploy nuclio - bad response:\n{resp.text}")
|
|
1577
|
+
raise ValueError("bad nuclio deploy response")
|
|
1578
|
+
|
|
1579
|
+
return resp.json()
|
|
1580
|
+
|
|
1581
|
+
def get_nuclio_deploy_status(
|
|
1582
|
+
self,
|
|
1583
|
+
func: mlrun.runtimes.RemoteRuntime,
|
|
1584
|
+
last_log_timestamp: float = 0.0,
|
|
1585
|
+
verbose: bool = False,
|
|
1586
|
+
):
|
|
1587
|
+
"""Retrieve the status of a deploy operation currently in progress.
|
|
1588
|
+
|
|
1589
|
+
:param func: Function object that is being built.
|
|
1590
|
+
:param last_log_timestamp: Last timestamp of logs that were already retrieved. Function will return only logs
|
|
1591
|
+
later than this parameter.
|
|
1592
|
+
:param verbose: Add verbose logs into the output.
|
|
1593
|
+
|
|
1594
|
+
:returns: The following parameters:
|
|
1595
|
+
|
|
1596
|
+
- Text of builder logs.
|
|
1597
|
+
- Timestamp of last log retrieved, to be used in subsequent calls to this function.
|
|
1598
|
+
"""
|
|
1599
|
+
|
|
1600
|
+
try:
|
|
1601
|
+
normalized_name = normalize_name(func.metadata.name)
|
|
1602
|
+
params = {
|
|
1603
|
+
"name": normalized_name,
|
|
1604
|
+
"project": func.metadata.project,
|
|
1605
|
+
"tag": func.metadata.tag,
|
|
1606
|
+
"last_log_timestamp": str(last_log_timestamp),
|
|
1607
|
+
"verbose": bool2str(verbose),
|
|
1608
|
+
}
|
|
1609
|
+
_path = f"projects/{func.metadata.project}/nuclio/{normalized_name}/deploy"
|
|
1610
|
+
resp = self.api_call("GET", _path, params=params)
|
|
1611
|
+
except OSError as err:
|
|
1612
|
+
logger.error(f"error getting deploy status: {err_to_str(err)}")
|
|
1613
|
+
raise OSError(f"error: cannot get deploy status, {err_to_str(err)}")
|
|
1614
|
+
|
|
1615
|
+
if not resp.ok:
|
|
1616
|
+
logger.warning(f"failed resp, {resp.text}")
|
|
1617
|
+
raise RunDBError("bad function build response")
|
|
1618
|
+
|
|
1619
|
+
if resp.headers:
|
|
1620
|
+
last_log_timestamp = float(
|
|
1621
|
+
resp.headers.get("x-mlrun-last-timestamp", "0.0")
|
|
1622
|
+
)
|
|
1623
|
+
mlrun.runtimes.nuclio.function.enrich_nuclio_function_from_headers(
|
|
1624
|
+
func, resp.headers
|
|
1625
|
+
)
|
|
1626
|
+
|
|
1627
|
+
text = ""
|
|
1628
|
+
if resp.content:
|
|
1629
|
+
text = resp.content.decode()
|
|
1630
|
+
return text, last_log_timestamp
|
|
1631
|
+
|
|
1380
1632
|
def get_builder_status(
|
|
1381
1633
|
self,
|
|
1382
1634
|
func: BaseRuntime,
|
|
@@ -1426,21 +1678,18 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1426
1678
|
last_log_timestamp = float(
|
|
1427
1679
|
resp.headers.get("x-mlrun-last-timestamp", "0.0")
|
|
1428
1680
|
)
|
|
1429
|
-
if func.kind in mlrun.runtimes.RuntimeKinds.
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
func.status.internal_invocation_urls = resp.headers.get(
|
|
1433
|
-
"x-mlrun-internal-invocation-urls", ""
|
|
1434
|
-
).split(",")
|
|
1435
|
-
func.status.external_invocation_urls = resp.headers.get(
|
|
1436
|
-
"x-mlrun-external-invocation-urls", ""
|
|
1437
|
-
).split(",")
|
|
1438
|
-
func.status.container_image = resp.headers.get(
|
|
1439
|
-
"x-mlrun-container-image", ""
|
|
1681
|
+
if func.kind in mlrun.runtimes.RuntimeKinds.pure_nuclio_deployed_runtimes():
|
|
1682
|
+
mlrun.runtimes.nuclio.function.enrich_nuclio_function_from_headers(
|
|
1683
|
+
func, resp.headers
|
|
1440
1684
|
)
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1685
|
+
|
|
1686
|
+
builder_pod = resp.headers.get("builder_pod", "")
|
|
1687
|
+
if builder_pod:
|
|
1688
|
+
func.status.build_pod = builder_pod
|
|
1689
|
+
|
|
1690
|
+
function_image = resp.headers.get("function_image", "")
|
|
1691
|
+
if function_image:
|
|
1692
|
+
func.spec.image = function_image
|
|
1444
1693
|
|
|
1445
1694
|
text = ""
|
|
1446
1695
|
if resp.content:
|
|
@@ -1503,7 +1752,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1503
1752
|
Retrieve updated information on project background tasks being executed.
|
|
1504
1753
|
If no filter is provided, will return background tasks from the last week.
|
|
1505
1754
|
|
|
1506
|
-
:param project: Project name (defaults to mlrun.
|
|
1755
|
+
:param project: Project name (defaults to mlrun.mlconf.default_project).
|
|
1507
1756
|
:param state: List only background tasks whose state is specified.
|
|
1508
1757
|
:param created_from: Filter by background task created time in ``[created_from, created_to]``.
|
|
1509
1758
|
:param created_to: Filter by background task created time in ``[created_from, created_to]``.
|
|
@@ -1616,32 +1865,31 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1616
1865
|
artifact_path=None,
|
|
1617
1866
|
ops=None,
|
|
1618
1867
|
cleanup_ttl=None,
|
|
1868
|
+
timeout=60,
|
|
1619
1869
|
):
|
|
1620
1870
|
"""Submit a KFP pipeline for execution.
|
|
1621
1871
|
|
|
1622
|
-
:param project:
|
|
1623
|
-
:param pipeline:
|
|
1624
|
-
:param arguments:
|
|
1625
|
-
:param experiment:
|
|
1626
|
-
:param run:
|
|
1627
|
-
:param namespace:
|
|
1628
|
-
:param artifact_path:
|
|
1629
|
-
:param ops:
|
|
1630
|
-
:param cleanup_ttl:
|
|
1631
|
-
|
|
1872
|
+
:param project: The project of the pipeline
|
|
1873
|
+
:param pipeline: Pipeline function or path to .yaml/.zip pipeline file.
|
|
1874
|
+
:param arguments: A dictionary of arguments to pass to the pipeline.
|
|
1875
|
+
:param experiment: A name to assign for the specific experiment.
|
|
1876
|
+
:param run: A name for this specific run.
|
|
1877
|
+
:param namespace: Kubernetes namespace to execute the pipeline in.
|
|
1878
|
+
:param artifact_path: A path to artifacts used by this pipeline.
|
|
1879
|
+
:param ops: Transformers to apply on all ops in the pipeline.
|
|
1880
|
+
:param cleanup_ttl: Pipeline cleanup ttl in secs (time to wait after workflow completion, at which point the
|
|
1881
|
+
workflow and all its resources are deleted)
|
|
1882
|
+
:param timeout: Timeout for the API call.
|
|
1632
1883
|
"""
|
|
1633
1884
|
|
|
1634
1885
|
if isinstance(pipeline, str):
|
|
1635
1886
|
pipe_file = pipeline
|
|
1636
1887
|
else:
|
|
1637
|
-
pipe_file =
|
|
1638
|
-
conf = new_pipe_metadata(
|
|
1888
|
+
pipe_file = compile_pipeline(
|
|
1639
1889
|
artifact_path=artifact_path,
|
|
1640
1890
|
cleanup_ttl=cleanup_ttl,
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
kfp.compiler.Compiler().compile(
|
|
1644
|
-
pipeline, pipe_file, type_check=False, pipeline_conf=conf
|
|
1891
|
+
ops=ops,
|
|
1892
|
+
pipeline=pipeline,
|
|
1645
1893
|
)
|
|
1646
1894
|
|
|
1647
1895
|
if pipe_file.endswith(".yaml"):
|
|
@@ -1670,7 +1918,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1670
1918
|
"POST",
|
|
1671
1919
|
f"projects/{project}/pipelines",
|
|
1672
1920
|
params=params,
|
|
1673
|
-
timeout=
|
|
1921
|
+
timeout=timeout,
|
|
1674
1922
|
body=data,
|
|
1675
1923
|
headers=headers,
|
|
1676
1924
|
)
|
|
@@ -1696,8 +1944,8 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1696
1944
|
page_token: str = "",
|
|
1697
1945
|
filter_: str = "",
|
|
1698
1946
|
format_: Union[
|
|
1699
|
-
str, mlrun.common.
|
|
1700
|
-
] = mlrun.common.
|
|
1947
|
+
str, mlrun.common.formatters.PipelineFormat
|
|
1948
|
+
] = mlrun.common.formatters.PipelineFormat.metadata_only,
|
|
1701
1949
|
page_size: int = None,
|
|
1702
1950
|
) -> mlrun.common.schemas.PipelinesOutput:
|
|
1703
1951
|
"""Retrieve a list of KFP pipelines. This function can be invoked to get all pipelines from all projects,
|
|
@@ -1743,8 +1991,8 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1743
1991
|
namespace: str = None,
|
|
1744
1992
|
timeout: int = 30,
|
|
1745
1993
|
format_: Union[
|
|
1746
|
-
str, mlrun.common.
|
|
1747
|
-
] = mlrun.common.
|
|
1994
|
+
str, mlrun.common.formatters.PipelineFormat
|
|
1995
|
+
] = mlrun.common.formatters.PipelineFormat.summary,
|
|
1748
1996
|
project: str = None,
|
|
1749
1997
|
):
|
|
1750
1998
|
"""Retrieve details of a specific pipeline using its run ID (as provided when the pipeline was executed)."""
|
|
@@ -1868,6 +2116,41 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1868
2116
|
resp = self.api_call("GET", path, error_message, params=params)
|
|
1869
2117
|
return resp.json()["features"]
|
|
1870
2118
|
|
|
2119
|
+
def list_features_v2(
|
|
2120
|
+
self,
|
|
2121
|
+
project: str,
|
|
2122
|
+
name: str = None,
|
|
2123
|
+
tag: str = None,
|
|
2124
|
+
entities: list[str] = None,
|
|
2125
|
+
labels: list[str] = None,
|
|
2126
|
+
) -> dict[str, list[dict]]:
|
|
2127
|
+
"""List feature-sets which contain specific features. This function may return multiple versions of the same
|
|
2128
|
+
feature-set if a specific tag is not requested. Note that the various filters of this function actually
|
|
2129
|
+
refer to the feature-set object containing the features, not to the features themselves.
|
|
2130
|
+
|
|
2131
|
+
:param project: Project which contains these features.
|
|
2132
|
+
:param name: Name of the feature to look for. The name is used in a like query, and is not case-sensitive. For
|
|
2133
|
+
example, looking for ``feat`` will return features which are named ``MyFeature`` as well as ``defeat``.
|
|
2134
|
+
:param tag: Return feature-sets which contain the features looked for, and are tagged with the specific tag.
|
|
2135
|
+
:param entities: Return only feature-sets which contain an entity whose name is contained in this list.
|
|
2136
|
+
:param labels: Return only feature-sets which are labeled as requested.
|
|
2137
|
+
:returns: A list of features, and a list of their corresponding feature sets.
|
|
2138
|
+
"""
|
|
2139
|
+
|
|
2140
|
+
project = project or config.default_project
|
|
2141
|
+
params = {
|
|
2142
|
+
"name": name,
|
|
2143
|
+
"tag": tag,
|
|
2144
|
+
"entity": entities or [],
|
|
2145
|
+
"label": labels or [],
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
path = f"projects/{project}/features"
|
|
2149
|
+
|
|
2150
|
+
error_message = f"Failed listing features, project: {project}, query: {params}"
|
|
2151
|
+
resp = self.api_call("GET", path, error_message, params=params, version="v2")
|
|
2152
|
+
return resp.json()
|
|
2153
|
+
|
|
1871
2154
|
def list_entities(
|
|
1872
2155
|
self,
|
|
1873
2156
|
project: str,
|
|
@@ -1893,6 +2176,31 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1893
2176
|
resp = self.api_call("GET", path, error_message, params=params)
|
|
1894
2177
|
return resp.json()["entities"]
|
|
1895
2178
|
|
|
2179
|
+
def list_entities_v2(
|
|
2180
|
+
self,
|
|
2181
|
+
project: str,
|
|
2182
|
+
name: str = None,
|
|
2183
|
+
tag: str = None,
|
|
2184
|
+
labels: list[str] = None,
|
|
2185
|
+
) -> dict[str, list[dict]]:
|
|
2186
|
+
"""Retrieve a list of entities and their mapping to the containing feature-sets. This function is similar
|
|
2187
|
+
to the :py:func:`~list_features_v2` function, and uses the same logic. However, the entities are matched
|
|
2188
|
+
against the name rather than the features.
|
|
2189
|
+
"""
|
|
2190
|
+
|
|
2191
|
+
project = project or config.default_project
|
|
2192
|
+
params = {
|
|
2193
|
+
"name": name,
|
|
2194
|
+
"tag": tag,
|
|
2195
|
+
"label": labels or [],
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
path = f"projects/{project}/entities"
|
|
2199
|
+
|
|
2200
|
+
error_message = f"Failed listing entities, project: {project}, query: {params}"
|
|
2201
|
+
resp = self.api_call("GET", path, error_message, params=params, version="v2")
|
|
2202
|
+
return resp.json()
|
|
2203
|
+
|
|
1896
2204
|
@staticmethod
|
|
1897
2205
|
def _generate_partition_by_params(
|
|
1898
2206
|
partition_by_cls,
|
|
@@ -1929,6 +2237,9 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1929
2237
|
partition_order: Union[
|
|
1930
2238
|
mlrun.common.schemas.OrderType, str
|
|
1931
2239
|
] = mlrun.common.schemas.OrderType.desc,
|
|
2240
|
+
format_: Union[
|
|
2241
|
+
str, mlrun.common.formatters.FeatureSetFormat
|
|
2242
|
+
] = mlrun.common.formatters.FeatureSetFormat.full,
|
|
1932
2243
|
) -> list[FeatureSet]:
|
|
1933
2244
|
"""Retrieve a list of feature-sets matching the criteria provided.
|
|
1934
2245
|
|
|
@@ -1946,6 +2257,9 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1946
2257
|
:param partition_sort_by: What field to sort the results by, within each partition defined by `partition_by`.
|
|
1947
2258
|
Currently the only allowed value are `created` and `updated`.
|
|
1948
2259
|
:param partition_order: Order of sorting within partitions - `asc` or `desc`. Default is `desc`.
|
|
2260
|
+
:param format_: Format of the results. Possible values are:
|
|
2261
|
+
- ``minimal`` - Return minimal feature set objects, not including stats and preview for each feature set.
|
|
2262
|
+
- ``full`` - Return full feature set objects.
|
|
1949
2263
|
:returns: List of matching :py:class:`~mlrun.feature_store.FeatureSet` objects.
|
|
1950
2264
|
"""
|
|
1951
2265
|
|
|
@@ -1958,6 +2272,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
1958
2272
|
"entity": entities or [],
|
|
1959
2273
|
"feature": features or [],
|
|
1960
2274
|
"label": labels or [],
|
|
2275
|
+
"format": format_,
|
|
1961
2276
|
}
|
|
1962
2277
|
if partition_by:
|
|
1963
2278
|
params.update(
|
|
@@ -2044,7 +2359,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2044
2359
|
not a full object.
|
|
2045
2360
|
Example::
|
|
2046
2361
|
|
|
2047
|
-
feature_set_update = {"status": {"processed"
|
|
2362
|
+
feature_set_update = {"status": {"processed": True}}
|
|
2048
2363
|
|
|
2049
2364
|
Will apply the field ``status.processed`` to the existing object.
|
|
2050
2365
|
:param project: Project which contains the modified object.
|
|
@@ -2386,8 +2701,8 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2386
2701
|
self,
|
|
2387
2702
|
owner: str = None,
|
|
2388
2703
|
format_: Union[
|
|
2389
|
-
str, mlrun.common.
|
|
2390
|
-
] = mlrun.common.
|
|
2704
|
+
str, mlrun.common.formatters.ProjectFormat
|
|
2705
|
+
] = mlrun.common.formatters.ProjectFormat.name_only,
|
|
2391
2706
|
labels: list[str] = None,
|
|
2392
2707
|
state: Union[str, mlrun.common.schemas.ProjectState] = None,
|
|
2393
2708
|
) -> list[Union[mlrun.projects.MlrunProject, str]]:
|
|
@@ -2413,7 +2728,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2413
2728
|
|
|
2414
2729
|
error_message = f"Failed listing projects, query: {params}"
|
|
2415
2730
|
response = self.api_call("GET", "projects", error_message, params=params)
|
|
2416
|
-
if format_ == mlrun.common.
|
|
2731
|
+
if format_ == mlrun.common.formatters.ProjectFormat.name_only:
|
|
2417
2732
|
# projects is just a list of strings
|
|
2418
2733
|
return response.json()["projects"]
|
|
2419
2734
|
|
|
@@ -2441,7 +2756,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2441
2756
|
deletion_strategy: Union[
|
|
2442
2757
|
str, mlrun.common.schemas.DeletionStrategy
|
|
2443
2758
|
] = mlrun.common.schemas.DeletionStrategy.default(),
|
|
2444
|
-
):
|
|
2759
|
+
) -> None:
|
|
2445
2760
|
"""Delete a project.
|
|
2446
2761
|
|
|
2447
2762
|
:param name: Name of the project to delete.
|
|
@@ -2460,7 +2775,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2460
2775
|
"DELETE", f"projects/{name}", error_message, headers=headers, version="v2"
|
|
2461
2776
|
)
|
|
2462
2777
|
if response.status_code == http.HTTPStatus.ACCEPTED:
|
|
2463
|
-
logger.info("
|
|
2778
|
+
logger.info("Waiting for project to be deleted", project_name=name)
|
|
2464
2779
|
background_task = mlrun.common.schemas.BackgroundTask(**response.json())
|
|
2465
2780
|
background_task = self._wait_for_background_task_to_reach_terminal_state(
|
|
2466
2781
|
background_task.metadata.name
|
|
@@ -2470,10 +2785,17 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2470
2785
|
== mlrun.common.schemas.BackgroundTaskState.succeeded
|
|
2471
2786
|
):
|
|
2472
2787
|
logger.info("Project deleted", project_name=name)
|
|
2473
|
-
|
|
2788
|
+
elif (
|
|
2789
|
+
background_task.status.state
|
|
2790
|
+
== mlrun.common.schemas.BackgroundTaskState.failed
|
|
2791
|
+
):
|
|
2792
|
+
logger.error(
|
|
2793
|
+
"Project deletion failed",
|
|
2794
|
+
project_name=name,
|
|
2795
|
+
error=background_task.status.error,
|
|
2796
|
+
)
|
|
2474
2797
|
elif response.status_code == http.HTTPStatus.NO_CONTENT:
|
|
2475
2798
|
logger.info("Project deleted", project_name=name)
|
|
2476
|
-
return
|
|
2477
2799
|
|
|
2478
2800
|
def store_project(
|
|
2479
2801
|
self,
|
|
@@ -2618,11 +2940,11 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2618
2940
|
:param secrets: A set of secret values to store.
|
|
2619
2941
|
Example::
|
|
2620
2942
|
|
|
2621
|
-
secrets = {
|
|
2943
|
+
secrets = {"password": "myPassw0rd", "aws_key": "111222333"}
|
|
2622
2944
|
db.create_project_secrets(
|
|
2623
2945
|
"project1",
|
|
2624
2946
|
provider=mlrun.common.schemas.SecretProviderName.kubernetes,
|
|
2625
|
-
secrets=secrets
|
|
2947
|
+
secrets=secrets,
|
|
2626
2948
|
)
|
|
2627
2949
|
"""
|
|
2628
2950
|
path = f"projects/{project}/secrets"
|
|
@@ -2918,14 +3240,12 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2918
3240
|
:param labels: A list of labels to filter by. Label filters work by either filtering a specific value of a
|
|
2919
3241
|
label (i.e. list("key=value")) or by looking for the existence of a given key (i.e. "key")
|
|
2920
3242
|
:param metrics: A list of metrics to return for each endpoint, read more in 'TimeMetric'
|
|
2921
|
-
:param start: The start time of the metrics. Can be represented by a string containing an RFC 3339
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
`'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` =
|
|
2928
|
-
days), or 0 for the earliest time.
|
|
3243
|
+
:param start: The start time of the metrics. Can be represented by a string containing an RFC 3339 time, a
|
|
3244
|
+
Unix timestamp in milliseconds, a relative time (`'now'` or `'now-[0-9]+[mhd]'`, where
|
|
3245
|
+
`m` = minutes, `h` = hours, `'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
|
|
3246
|
+
:param end: The end time of the metrics. Can be represented by a string containing an RFC 3339 time, a
|
|
3247
|
+
Unix timestamp in milliseconds, a relative time (`'now'` or `'now-[0-9]+[mhd]'`, where
|
|
3248
|
+
`m` = minutes, `h` = hours, `'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
|
|
2929
3249
|
:param top_level: if true will return only routers and endpoint that are NOT children of any router
|
|
2930
3250
|
:param uids: if passed will return a list `ModelEndpoint` object with uid in uids
|
|
2931
3251
|
"""
|
|
@@ -2974,13 +3294,13 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2974
3294
|
:param project: The name of the project
|
|
2975
3295
|
:param endpoint_id: The unique id of the model endpoint.
|
|
2976
3296
|
:param start: The start time of the metrics. Can be represented by a string containing an
|
|
2977
|
-
RFC 3339 time, a
|
|
2978
|
-
`'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours,
|
|
2979
|
-
0 for the earliest time.
|
|
3297
|
+
RFC 3339 time, a Unix timestamp in milliseconds, a relative time
|
|
3298
|
+
(`'now'` or `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours,
|
|
3299
|
+
`'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
|
|
2980
3300
|
:param end: The end time of the metrics. Can be represented by a string containing an
|
|
2981
|
-
RFC 3339 time, a
|
|
2982
|
-
`'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours,
|
|
2983
|
-
0 for the earliest time.
|
|
3301
|
+
RFC 3339 time, a Unix timestamp in milliseconds, a relative time
|
|
3302
|
+
(`'now'` or `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours,
|
|
3303
|
+
`'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
|
|
2984
3304
|
:param metrics: A list of metrics to return for the model endpoint. There are pre-defined
|
|
2985
3305
|
metrics for model endpoints such as predictions_per_second and
|
|
2986
3306
|
latency_avg_5m but also custom metrics defined by the user. Please note that
|
|
@@ -2989,7 +3309,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
2989
3309
|
:param feature_analysis: When True, the base feature statistics and current feature statistics will
|
|
2990
3310
|
be added to the output of the resulting object.
|
|
2991
3311
|
|
|
2992
|
-
:
|
|
3312
|
+
:returns: A `ModelEndpoint` object.
|
|
2993
3313
|
"""
|
|
2994
3314
|
|
|
2995
3315
|
path = f"projects/{project}/model-endpoints/{endpoint_id}"
|
|
@@ -3050,41 +3370,12 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3050
3370
|
params=attributes,
|
|
3051
3371
|
)
|
|
3052
3372
|
|
|
3053
|
-
def deploy_monitoring_batch_job(
|
|
3054
|
-
self,
|
|
3055
|
-
project: str = "",
|
|
3056
|
-
default_batch_image: str = "mlrun/mlrun",
|
|
3057
|
-
with_schedule: bool = False,
|
|
3058
|
-
):
|
|
3059
|
-
"""
|
|
3060
|
-
Submit model monitoring batch job. By default, submit only the batch job as ML function without scheduling.
|
|
3061
|
-
To submit a scheduled job as well, please set with_schedule = True.
|
|
3062
|
-
|
|
3063
|
-
:param project: Project name.
|
|
3064
|
-
:param default_batch_image: The default image of the model monitoring batch job. By default, the image
|
|
3065
|
-
is mlrun/mlrun.
|
|
3066
|
-
:param with_schedule: If true, submit the model monitoring scheduled job as well.
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
:returns: model monitoring batch job as a dictionary. You can easily convert the returned function into a
|
|
3070
|
-
runtime object by calling ~mlrun.new_function.
|
|
3071
|
-
"""
|
|
3072
|
-
|
|
3073
|
-
params = {
|
|
3074
|
-
"default_batch_image": default_batch_image,
|
|
3075
|
-
"with_schedule": with_schedule,
|
|
3076
|
-
}
|
|
3077
|
-
path = f"projects/{project}/jobs/batch-monitoring"
|
|
3078
|
-
|
|
3079
|
-
resp = self.api_call(method="POST", path=path, params=params)
|
|
3080
|
-
return resp.json()["func"]
|
|
3081
|
-
|
|
3082
3373
|
def update_model_monitoring_controller(
|
|
3083
3374
|
self,
|
|
3084
3375
|
project: str,
|
|
3085
3376
|
base_period: int = 10,
|
|
3086
3377
|
image: str = "mlrun/mlrun",
|
|
3087
|
-
):
|
|
3378
|
+
) -> None:
|
|
3088
3379
|
"""
|
|
3089
3380
|
Redeploy model monitoring application controller function.
|
|
3090
3381
|
|
|
@@ -3094,20 +3385,24 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3094
3385
|
:param image: The image of the model monitoring controller function.
|
|
3095
3386
|
By default, the image is mlrun/mlrun.
|
|
3096
3387
|
"""
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
"
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3388
|
+
self.api_call(
|
|
3389
|
+
method=mlrun.common.types.HTTPMethod.PATCH,
|
|
3390
|
+
path=f"projects/{project}/model-monitoring/model-monitoring-controller",
|
|
3391
|
+
params={
|
|
3392
|
+
"base_period": base_period,
|
|
3393
|
+
"image": image,
|
|
3394
|
+
},
|
|
3395
|
+
)
|
|
3104
3396
|
|
|
3105
3397
|
def enable_model_monitoring(
|
|
3106
3398
|
self,
|
|
3107
3399
|
project: str,
|
|
3108
3400
|
base_period: int = 10,
|
|
3109
3401
|
image: str = "mlrun/mlrun",
|
|
3110
|
-
|
|
3402
|
+
deploy_histogram_data_drift_app: bool = True,
|
|
3403
|
+
rebuild_images: bool = False,
|
|
3404
|
+
fetch_credentials_from_sys_config: bool = False,
|
|
3405
|
+
) -> None:
|
|
3111
3406
|
"""
|
|
3112
3407
|
Deploy model monitoring application controller, writer and stream functions.
|
|
3113
3408
|
While the main goal of the controller function is to handle the monitoring processing and triggering
|
|
@@ -3116,21 +3411,169 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3116
3411
|
The stream function goal is to monitor the log of the data stream. It is triggered when a new log entry
|
|
3117
3412
|
is detected. It processes the new events into statistics that are then written to statistics databases.
|
|
3118
3413
|
|
|
3414
|
+
:param project: Project name.
|
|
3415
|
+
:param base_period: The time period in minutes in which the model monitoring controller
|
|
3416
|
+
function triggers. By default, the base period is 10 minutes.
|
|
3417
|
+
:param image: The image of the model monitoring controller, writer & monitoring
|
|
3418
|
+
stream functions, which are real time nuclio functions.
|
|
3419
|
+
By default, the image is mlrun/mlrun.
|
|
3420
|
+
:param deploy_histogram_data_drift_app: If true, deploy the default histogram-based data drift application.
|
|
3421
|
+
:param rebuild_images: If true, force rebuild of model monitoring infrastructure images.
|
|
3422
|
+
:param fetch_credentials_from_sys_config: If true, fetch the credentials from the system configuration.
|
|
3119
3423
|
|
|
3120
|
-
:param project: Project name.
|
|
3121
|
-
:param base_period: The time period in minutes in which the model monitoring controller function
|
|
3122
|
-
triggers. By default, the base period is 10 minutes.
|
|
3123
|
-
:param image: The image of the model monitoring controller, writer & monitoring
|
|
3124
|
-
stream functions, which are real time nuclio functions.
|
|
3125
|
-
By default, the image is mlrun/mlrun.
|
|
3126
3424
|
"""
|
|
3425
|
+
self.api_call(
|
|
3426
|
+
method=mlrun.common.types.HTTPMethod.POST,
|
|
3427
|
+
path=f"projects/{project}/model-monitoring/enable-model-monitoring",
|
|
3428
|
+
params={
|
|
3429
|
+
"base_period": base_period,
|
|
3430
|
+
"image": image,
|
|
3431
|
+
"deploy_histogram_data_drift_app": deploy_histogram_data_drift_app,
|
|
3432
|
+
"rebuild_images": rebuild_images,
|
|
3433
|
+
"fetch_credentials_from_sys_config": fetch_credentials_from_sys_config,
|
|
3434
|
+
},
|
|
3435
|
+
)
|
|
3127
3436
|
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3437
|
+
def disable_model_monitoring(
|
|
3438
|
+
self,
|
|
3439
|
+
project: str,
|
|
3440
|
+
delete_resources: bool = True,
|
|
3441
|
+
delete_stream_function: bool = False,
|
|
3442
|
+
delete_histogram_data_drift_app: bool = True,
|
|
3443
|
+
delete_user_applications: bool = False,
|
|
3444
|
+
user_application_list: list[str] = None,
|
|
3445
|
+
) -> bool:
|
|
3446
|
+
"""
|
|
3447
|
+
Disable model monitoring application controller, writer, stream, histogram data drift application
|
|
3448
|
+
and the user's applications functions, according to the given params.
|
|
3449
|
+
|
|
3450
|
+
:param project: Project name.
|
|
3451
|
+
:param delete_resources: If True, it would delete the model monitoring controller & writer
|
|
3452
|
+
functions. Default True
|
|
3453
|
+
:param delete_stream_function: If True, it would delete model monitoring stream function,
|
|
3454
|
+
need to use wisely because if you're deleting this function
|
|
3455
|
+
this can cause data loss in case you will want to
|
|
3456
|
+
enable the model monitoring capability to the project.
|
|
3457
|
+
Default False.
|
|
3458
|
+
:param delete_histogram_data_drift_app: If True, it would delete the default histogram-based data drift
|
|
3459
|
+
application. Default False.
|
|
3460
|
+
:param delete_user_applications: If True, it would delete the user's model monitoring
|
|
3461
|
+
application according to user_application_list, Default False.
|
|
3462
|
+
:param user_application_list: List of the user's model monitoring application to disable.
|
|
3463
|
+
Default all the applications.
|
|
3464
|
+
Note: you have to set delete_user_applications to True
|
|
3465
|
+
in order to delete the desired application.
|
|
3466
|
+
|
|
3467
|
+
:returns: True if the deletion was successful, False otherwise.
|
|
3468
|
+
"""
|
|
3469
|
+
response = self.api_call(
|
|
3470
|
+
method=mlrun.common.types.HTTPMethod.DELETE,
|
|
3471
|
+
path=f"projects/{project}/model-monitoring/disable-model-monitoring",
|
|
3472
|
+
params={
|
|
3473
|
+
"delete_resources": delete_resources,
|
|
3474
|
+
"delete_stream_function": delete_stream_function,
|
|
3475
|
+
"delete_histogram_data_drift_app": delete_histogram_data_drift_app,
|
|
3476
|
+
"delete_user_applications": delete_user_applications,
|
|
3477
|
+
"user_application_list": user_application_list,
|
|
3478
|
+
},
|
|
3479
|
+
)
|
|
3480
|
+
deletion_failed = False
|
|
3481
|
+
if response.status_code == http.HTTPStatus.ACCEPTED:
|
|
3482
|
+
if delete_resources:
|
|
3483
|
+
logger.info(
|
|
3484
|
+
"Model Monitoring is being disabled",
|
|
3485
|
+
project_name=project,
|
|
3486
|
+
)
|
|
3487
|
+
if delete_user_applications:
|
|
3488
|
+
logger.info("User applications are being deleted", project_name=project)
|
|
3489
|
+
background_tasks = mlrun.common.schemas.BackgroundTaskList(
|
|
3490
|
+
**response.json()
|
|
3491
|
+
).background_tasks
|
|
3492
|
+
for task in background_tasks:
|
|
3493
|
+
task = self._wait_for_background_task_to_reach_terminal_state(
|
|
3494
|
+
task.metadata.name, project=project
|
|
3495
|
+
)
|
|
3496
|
+
if (
|
|
3497
|
+
task.status.state
|
|
3498
|
+
== mlrun.common.schemas.BackgroundTaskState.succeeded
|
|
3499
|
+
):
|
|
3500
|
+
continue
|
|
3501
|
+
elif (
|
|
3502
|
+
task.status.state == mlrun.common.schemas.BackgroundTaskState.failed
|
|
3503
|
+
):
|
|
3504
|
+
deletion_failed = True
|
|
3505
|
+
return not deletion_failed
|
|
3506
|
+
|
|
3507
|
+
def delete_model_monitoring_function(
|
|
3508
|
+
self, project: str, functions: list[str]
|
|
3509
|
+
) -> bool:
|
|
3510
|
+
"""
|
|
3511
|
+
Delete a model monitoring application.
|
|
3512
|
+
|
|
3513
|
+
:param functions: List of the model monitoring function to delete.
|
|
3514
|
+
:param project: Project name.
|
|
3515
|
+
|
|
3516
|
+
:returns: True if the deletion was successful, False otherwise.
|
|
3517
|
+
"""
|
|
3518
|
+
response = self.api_call(
|
|
3519
|
+
method=mlrun.common.types.HTTPMethod.DELETE,
|
|
3520
|
+
path=f"projects/{project}/model-monitoring/functions",
|
|
3521
|
+
params={"functions": functions},
|
|
3522
|
+
)
|
|
3523
|
+
deletion_failed = False
|
|
3524
|
+
if response.status_code == http.HTTPStatus.ACCEPTED:
|
|
3525
|
+
logger.info("User applications are being deleted", project_name=project)
|
|
3526
|
+
background_tasks = mlrun.common.schemas.BackgroundTaskList(
|
|
3527
|
+
**response.json()
|
|
3528
|
+
).background_tasks
|
|
3529
|
+
for task in background_tasks:
|
|
3530
|
+
task = self._wait_for_background_task_to_reach_terminal_state(
|
|
3531
|
+
task.metadata.name, project=project
|
|
3532
|
+
)
|
|
3533
|
+
if (
|
|
3534
|
+
task.status.state
|
|
3535
|
+
== mlrun.common.schemas.BackgroundTaskState.succeeded
|
|
3536
|
+
):
|
|
3537
|
+
continue
|
|
3538
|
+
elif (
|
|
3539
|
+
task.status.state == mlrun.common.schemas.BackgroundTaskState.failed
|
|
3540
|
+
):
|
|
3541
|
+
deletion_failed = True
|
|
3542
|
+
return not deletion_failed
|
|
3543
|
+
|
|
3544
|
+
def deploy_histogram_data_drift_app(
|
|
3545
|
+
self, project: str, image: str = "mlrun/mlrun"
|
|
3546
|
+
) -> None:
|
|
3547
|
+
"""
|
|
3548
|
+
Deploy the histogram data drift application.
|
|
3549
|
+
|
|
3550
|
+
:param project: Project name.
|
|
3551
|
+
:param image: The image on which the application will run.
|
|
3552
|
+
"""
|
|
3553
|
+
self.api_call(
|
|
3554
|
+
method=mlrun.common.types.HTTPMethod.POST,
|
|
3555
|
+
path=f"projects/{project}/model-monitoring/deploy-histogram-data-drift-app",
|
|
3556
|
+
params={"image": image},
|
|
3557
|
+
)
|
|
3558
|
+
|
|
3559
|
+
def set_model_monitoring_credentials(
|
|
3560
|
+
self,
|
|
3561
|
+
project: str,
|
|
3562
|
+
credentials: dict[str, str],
|
|
3563
|
+
replace_creds: bool,
|
|
3564
|
+
) -> None:
|
|
3565
|
+
"""
|
|
3566
|
+
Set the credentials for the model monitoring application.
|
|
3567
|
+
|
|
3568
|
+
:param project: Project name.
|
|
3569
|
+
:param credentials: Credentials to set.
|
|
3570
|
+
:param replace_creds: If True, will override the existing credentials.
|
|
3571
|
+
"""
|
|
3572
|
+
self.api_call(
|
|
3573
|
+
method=mlrun.common.types.HTTPMethod.POST,
|
|
3574
|
+
path=f"projects/{project}/model-monitoring/set-model-monitoring-credentials",
|
|
3575
|
+
params={**credentials, "replace_creds": replace_creds},
|
|
3576
|
+
)
|
|
3134
3577
|
|
|
3135
3578
|
def create_hub_source(
|
|
3136
3579
|
self, source: Union[dict, mlrun.common.schemas.IndexedHubSource]
|
|
@@ -3161,8 +3604,10 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3161
3604
|
metadata=mlrun.common.schemas.HubObjectMetadata(
|
|
3162
3605
|
name="priv", description="a private source"
|
|
3163
3606
|
),
|
|
3164
|
-
spec=mlrun.common.schemas.HubSourceSpec(
|
|
3165
|
-
|
|
3607
|
+
spec=mlrun.common.schemas.HubSourceSpec(
|
|
3608
|
+
path="/local/path/to/source", channel="development"
|
|
3609
|
+
),
|
|
3610
|
+
),
|
|
3166
3611
|
)
|
|
3167
3612
|
db.create_hub_source(private_source)
|
|
3168
3613
|
|
|
@@ -3176,9 +3621,9 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3176
3621
|
spec=mlrun.common.schemas.HubSourceSpec(
|
|
3177
3622
|
path="/local/path/to/source/2",
|
|
3178
3623
|
channel="development",
|
|
3179
|
-
credentials={...}
|
|
3180
|
-
)
|
|
3181
|
-
)
|
|
3624
|
+
credentials={...},
|
|
3625
|
+
),
|
|
3626
|
+
),
|
|
3182
3627
|
)
|
|
3183
3628
|
db.create_hub_source(another_source)
|
|
3184
3629
|
|
|
@@ -3342,7 +3787,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3342
3787
|
:param version: Get a specific version of the item. Default is ``None``.
|
|
3343
3788
|
:param tag: Get a specific version of the item identified by tag. Default is ``latest``.
|
|
3344
3789
|
|
|
3345
|
-
:
|
|
3790
|
+
:returns: http response with the asset in the content attribute
|
|
3346
3791
|
"""
|
|
3347
3792
|
path = f"hub/sources/{source_name}/items/{item_name}/assets/{asset_name}"
|
|
3348
3793
|
params = {
|
|
@@ -3373,9 +3818,10 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3373
3818
|
def list_api_gateways(self, project=None) -> mlrun.common.schemas.APIGatewaysOutput:
|
|
3374
3819
|
"""
|
|
3375
3820
|
Returns a list of Nuclio api gateways
|
|
3821
|
+
|
|
3376
3822
|
:param project: optional str parameter to filter by project, if not passed, default project value is taken
|
|
3377
3823
|
|
|
3378
|
-
:
|
|
3824
|
+
:returns: :py:class:`~mlrun.common.schemas.APIGateways`.
|
|
3379
3825
|
"""
|
|
3380
3826
|
project = project or config.default_project
|
|
3381
3827
|
error = "list api gateways"
|
|
@@ -3386,10 +3832,11 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3386
3832
|
def get_api_gateway(self, name, project=None) -> mlrun.common.schemas.APIGateway:
|
|
3387
3833
|
"""
|
|
3388
3834
|
Returns an API gateway
|
|
3835
|
+
|
|
3389
3836
|
:param name: API gateway name
|
|
3390
3837
|
:param project: optional str parameter to filter by project, if not passed, default project value is taken
|
|
3391
3838
|
|
|
3392
|
-
:
|
|
3839
|
+
:returns: :py:class:`~mlrun.common.schemas.APIGateway`.
|
|
3393
3840
|
"""
|
|
3394
3841
|
project = project or config.default_project
|
|
3395
3842
|
error = "get api gateway"
|
|
@@ -3397,6 +3844,18 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3397
3844
|
response = self.api_call("GET", endpoint_path, error)
|
|
3398
3845
|
return mlrun.common.schemas.APIGateway(**response.json())
|
|
3399
3846
|
|
|
3847
|
+
def delete_api_gateway(self, name, project=None):
|
|
3848
|
+
"""
|
|
3849
|
+
Deletes an API gateway
|
|
3850
|
+
|
|
3851
|
+
:param name: API gateway name
|
|
3852
|
+
:param project: Project name
|
|
3853
|
+
"""
|
|
3854
|
+
project = project or config.default_project
|
|
3855
|
+
error = "delete api gateway"
|
|
3856
|
+
endpoint_path = f"projects/{project}/api-gateways/{name}"
|
|
3857
|
+
self.api_call("DELETE", endpoint_path, error)
|
|
3858
|
+
|
|
3400
3859
|
def store_api_gateway(
|
|
3401
3860
|
self,
|
|
3402
3861
|
api_gateway: Union[
|
|
@@ -3407,11 +3866,12 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3407
3866
|
) -> mlrun.common.schemas.APIGateway:
|
|
3408
3867
|
"""
|
|
3409
3868
|
Stores an API Gateway.
|
|
3410
|
-
|
|
3869
|
+
|
|
3870
|
+
:param api_gateway: :py:class:`~mlrun.runtimes.nuclio.APIGateway`
|
|
3411
3871
|
or :py:class:`~mlrun.common.schemas.APIGateway`: API Gateway entity.
|
|
3412
3872
|
:param project: project name. Mandatory if api_gateway is mlrun.common.schemas.APIGateway.
|
|
3413
3873
|
|
|
3414
|
-
:
|
|
3874
|
+
:returns: :py:class:`~mlrun.common.schemas.APIGateway`.
|
|
3415
3875
|
"""
|
|
3416
3876
|
|
|
3417
3877
|
if isinstance(api_gateway, mlrun.runtimes.nuclio.api_gateway.APIGateway):
|
|
@@ -3422,13 +3882,14 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3422
3882
|
"PUT",
|
|
3423
3883
|
endpoint_path,
|
|
3424
3884
|
error,
|
|
3425
|
-
json=api_gateway.dict(
|
|
3885
|
+
json=api_gateway.dict(exclude_none=True),
|
|
3426
3886
|
)
|
|
3427
3887
|
return mlrun.common.schemas.APIGateway(**response.json())
|
|
3428
3888
|
|
|
3429
3889
|
def trigger_migrations(self) -> Optional[mlrun.common.schemas.BackgroundTask]:
|
|
3430
3890
|
"""Trigger migrations (will do nothing if no migrations are needed) and wait for them to finish if actually
|
|
3431
3891
|
triggered
|
|
3892
|
+
|
|
3432
3893
|
:returns: :py:class:`~mlrun.common.schemas.BackgroundTask`.
|
|
3433
3894
|
"""
|
|
3434
3895
|
response = self.api_call(
|
|
@@ -3451,6 +3912,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3451
3912
|
):
|
|
3452
3913
|
"""
|
|
3453
3914
|
Set notifications on a run. This will override any existing notifications on the run.
|
|
3915
|
+
|
|
3454
3916
|
:param project: Project containing the run.
|
|
3455
3917
|
:param run_uid: UID of the run.
|
|
3456
3918
|
:param notifications: List of notifications to set on the run. Default is an empty list.
|
|
@@ -3476,6 +3938,7 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3476
3938
|
):
|
|
3477
3939
|
"""
|
|
3478
3940
|
Set notifications on a schedule. This will override any existing notifications on the schedule.
|
|
3941
|
+
|
|
3479
3942
|
:param project: Project containing the schedule.
|
|
3480
3943
|
:param schedule_name: Name of the schedule.
|
|
3481
3944
|
:param notifications: List of notifications to set on the schedule. Default is an empty list.
|
|
@@ -3507,6 +3970,16 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3507
3970
|
"""
|
|
3508
3971
|
pass
|
|
3509
3972
|
|
|
3973
|
+
def store_alert_notifications(
|
|
3974
|
+
self,
|
|
3975
|
+
session,
|
|
3976
|
+
notification_objects: list[mlrun.model.Notification],
|
|
3977
|
+
alert_id: str,
|
|
3978
|
+
project: str,
|
|
3979
|
+
mask_params: bool = True,
|
|
3980
|
+
):
|
|
3981
|
+
pass
|
|
3982
|
+
|
|
3510
3983
|
def submit_workflow(
|
|
3511
3984
|
self,
|
|
3512
3985
|
project: str,
|
|
@@ -3614,15 +4087,16 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3614
4087
|
) -> str:
|
|
3615
4088
|
"""
|
|
3616
4089
|
Loading a project remotely from the given source.
|
|
4090
|
+
|
|
3617
4091
|
:param name: project name
|
|
3618
4092
|
:param url: git or tar.gz or .zip sources archive path e.g.:
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
4093
|
+
git://github.com/mlrun/demo-xgb-project.git
|
|
4094
|
+
http://mysite/archived-project.zip
|
|
4095
|
+
The git project should include the project yaml file.
|
|
3622
4096
|
:param secrets: Secrets to store in project in order to load it from the provided url. For more
|
|
3623
|
-
|
|
4097
|
+
information see :py:func:`mlrun.load_project` function.
|
|
3624
4098
|
:param save_secrets: Whether to store secrets in the loaded project. Setting to False will cause waiting
|
|
3625
|
-
|
|
4099
|
+
for the process completion.
|
|
3626
4100
|
|
|
3627
4101
|
:returns: The terminal state of load project process.
|
|
3628
4102
|
"""
|
|
@@ -3698,6 +4172,168 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3698
4172
|
|
|
3699
4173
|
self.api_call(method="PUT", path=_path, json=profile.dict())
|
|
3700
4174
|
|
|
4175
|
+
@staticmethod
|
|
4176
|
+
def warn_on_s3_and_ecr_permissions_conflict(func):
|
|
4177
|
+
is_s3_source = func.spec.build.source and func.spec.build.source.startswith(
|
|
4178
|
+
"s3://"
|
|
4179
|
+
)
|
|
4180
|
+
is_ecr_image = mlrun.utils.is_ecr_url(config.httpdb.builder.docker_registry)
|
|
4181
|
+
if not func.spec.build.load_source_on_run and is_s3_source and is_ecr_image:
|
|
4182
|
+
logger.warning(
|
|
4183
|
+
"Building a function image to ECR and loading an S3 source to the image may require conflicting access "
|
|
4184
|
+
"keys. Only the permissions granted to the platform's configured secret will take affect "
|
|
4185
|
+
"(see mlrun.mlconf.httpdb.builder.docker_registry_secret). "
|
|
4186
|
+
"In case the permissions are limited to ECR scope, you may use pull_at_runtime=True instead",
|
|
4187
|
+
source=func.spec.build.source,
|
|
4188
|
+
load_source_on_run=func.spec.build.load_source_on_run,
|
|
4189
|
+
default_docker_registry=config.httpdb.builder.docker_registry,
|
|
4190
|
+
)
|
|
4191
|
+
|
|
4192
|
+
def generate_event(
|
|
4193
|
+
self, name: str, event_data: Union[dict, mlrun.common.schemas.Event], project=""
|
|
4194
|
+
):
|
|
4195
|
+
"""
|
|
4196
|
+
Generate an event.
|
|
4197
|
+
|
|
4198
|
+
:param name: The name of the event.
|
|
4199
|
+
:param event_data: The data of the event.
|
|
4200
|
+
:param project: The project that the event belongs to.
|
|
4201
|
+
"""
|
|
4202
|
+
if mlrun.mlconf.alerts.mode == mlrun.common.schemas.alert.AlertsModes.disabled:
|
|
4203
|
+
logger.warning("Alerts are disabled, event will not be generated")
|
|
4204
|
+
|
|
4205
|
+
project = project or config.default_project
|
|
4206
|
+
endpoint_path = f"projects/{project}/events/{name}"
|
|
4207
|
+
error_message = f"post event {project}/events/{name}"
|
|
4208
|
+
if isinstance(event_data, mlrun.common.schemas.Event):
|
|
4209
|
+
event_data = event_data.dict()
|
|
4210
|
+
self.api_call(
|
|
4211
|
+
"POST", endpoint_path, error_message, body=dict_to_json(event_data)
|
|
4212
|
+
)
|
|
4213
|
+
|
|
4214
|
+
def store_alert_config(
|
|
4215
|
+
self,
|
|
4216
|
+
alert_name: str,
|
|
4217
|
+
alert_data: Union[dict, AlertConfig],
|
|
4218
|
+
project="",
|
|
4219
|
+
) -> AlertConfig:
|
|
4220
|
+
"""
|
|
4221
|
+
Create/modify an alert.
|
|
4222
|
+
|
|
4223
|
+
:param alert_name: The name of the alert.
|
|
4224
|
+
:param alert_data: The data of the alert.
|
|
4225
|
+
:param project: The project that the alert belongs to.
|
|
4226
|
+
:returns: The created/modified alert.
|
|
4227
|
+
"""
|
|
4228
|
+
if not alert_data:
|
|
4229
|
+
raise mlrun.errors.MLRunInvalidArgumentError("Alert data must be provided")
|
|
4230
|
+
|
|
4231
|
+
if mlrun.mlconf.alerts.mode == mlrun.common.schemas.alert.AlertsModes.disabled:
|
|
4232
|
+
logger.warning(
|
|
4233
|
+
"Alerts are disabled, alert will still be stored but will not be triggered"
|
|
4234
|
+
)
|
|
4235
|
+
|
|
4236
|
+
project = project or config.default_project
|
|
4237
|
+
endpoint_path = f"projects/{project}/alerts/{alert_name}"
|
|
4238
|
+
error_message = f"put alert {project}/alerts/{alert_name}"
|
|
4239
|
+
alert_instance = (
|
|
4240
|
+
alert_data
|
|
4241
|
+
if isinstance(alert_data, AlertConfig)
|
|
4242
|
+
else AlertConfig.from_dict(alert_data)
|
|
4243
|
+
)
|
|
4244
|
+
# Validation is necessary here because users can directly invoke this function
|
|
4245
|
+
# through `mlrun.get_run_db().store_alert_config()`.
|
|
4246
|
+
alert_instance.validate_required_fields()
|
|
4247
|
+
|
|
4248
|
+
alert_data = alert_instance.to_dict()
|
|
4249
|
+
body = _as_json(alert_data)
|
|
4250
|
+
response = self.api_call("PUT", endpoint_path, error_message, body=body)
|
|
4251
|
+
return AlertConfig.from_dict(response.json())
|
|
4252
|
+
|
|
4253
|
+
def get_alert_config(self, alert_name: str, project="") -> AlertConfig:
|
|
4254
|
+
"""
|
|
4255
|
+
Retrieve an alert.
|
|
4256
|
+
|
|
4257
|
+
:param alert_name: The name of the alert to retrieve.
|
|
4258
|
+
:param project: The project that the alert belongs to.
|
|
4259
|
+
|
|
4260
|
+
:returns: The alert object.
|
|
4261
|
+
"""
|
|
4262
|
+
project = project or config.default_project
|
|
4263
|
+
endpoint_path = f"projects/{project}/alerts/{alert_name}"
|
|
4264
|
+
error_message = f"get alert {project}/alerts/{alert_name}"
|
|
4265
|
+
response = self.api_call("GET", endpoint_path, error_message)
|
|
4266
|
+
return AlertConfig.from_dict(response.json())
|
|
4267
|
+
|
|
4268
|
+
def list_alerts_configs(self, project="") -> list[AlertConfig]:
|
|
4269
|
+
"""
|
|
4270
|
+
Retrieve list of alerts of a project.
|
|
4271
|
+
|
|
4272
|
+
:param project: The project name.
|
|
4273
|
+
|
|
4274
|
+
:returns: All the alerts objects of the project.
|
|
4275
|
+
"""
|
|
4276
|
+
project = project or config.default_project
|
|
4277
|
+
endpoint_path = f"projects/{project}/alerts"
|
|
4278
|
+
error_message = f"get alerts {project}/alerts"
|
|
4279
|
+
response = self.api_call("GET", endpoint_path, error_message).json()
|
|
4280
|
+
results = []
|
|
4281
|
+
for item in response:
|
|
4282
|
+
results.append(AlertConfig(**item))
|
|
4283
|
+
return results
|
|
4284
|
+
|
|
4285
|
+
def delete_alert_config(self, alert_name: str, project=""):
|
|
4286
|
+
"""
|
|
4287
|
+
Delete an alert.
|
|
4288
|
+
:param alert_name: The name of the alert to delete.
|
|
4289
|
+
:param project: The project that the alert belongs to.
|
|
4290
|
+
"""
|
|
4291
|
+
project = project or config.default_project
|
|
4292
|
+
endpoint_path = f"projects/{project}/alerts/{alert_name}"
|
|
4293
|
+
error_message = f"delete alert {project}/alerts/{alert_name}"
|
|
4294
|
+
self.api_call("DELETE", endpoint_path, error_message)
|
|
4295
|
+
|
|
4296
|
+
def reset_alert_config(self, alert_name: str, project=""):
|
|
4297
|
+
"""
|
|
4298
|
+
Reset an alert.
|
|
4299
|
+
|
|
4300
|
+
:param alert_name: The name of the alert to reset.
|
|
4301
|
+
:param project: The project that the alert belongs to.
|
|
4302
|
+
"""
|
|
4303
|
+
project = project or config.default_project
|
|
4304
|
+
endpoint_path = f"projects/{project}/alerts/{alert_name}/reset"
|
|
4305
|
+
error_message = f"post alert {project}/alerts/{alert_name}/reset"
|
|
4306
|
+
self.api_call("POST", endpoint_path, error_message)
|
|
4307
|
+
|
|
4308
|
+
def get_alert_template(
|
|
4309
|
+
self, template_name: str
|
|
4310
|
+
) -> mlrun.common.schemas.AlertTemplate:
|
|
4311
|
+
"""
|
|
4312
|
+
Retrieve a specific alert template.
|
|
4313
|
+
|
|
4314
|
+
:param template_name: The name of the template to retrieve.
|
|
4315
|
+
|
|
4316
|
+
:returns: The template object.
|
|
4317
|
+
"""
|
|
4318
|
+
endpoint_path = f"alert-templates/{template_name}"
|
|
4319
|
+
error_message = f"get template alert-templates/{template_name}"
|
|
4320
|
+
response = self.api_call("GET", endpoint_path, error_message)
|
|
4321
|
+
return mlrun.common.schemas.AlertTemplate(**response.json())
|
|
4322
|
+
|
|
4323
|
+
def list_alert_templates(self) -> list[mlrun.common.schemas.AlertTemplate]:
|
|
4324
|
+
"""
|
|
4325
|
+
Retrieve list of all alert templates.
|
|
4326
|
+
|
|
4327
|
+
:returns: All the alert template objects in the database.
|
|
4328
|
+
"""
|
|
4329
|
+
endpoint_path = "alert-templates"
|
|
4330
|
+
error_message = "get templates /alert-templates"
|
|
4331
|
+
response = self.api_call("GET", endpoint_path, error_message).json()
|
|
4332
|
+
results = []
|
|
4333
|
+
for item in response:
|
|
4334
|
+
results.append(mlrun.common.schemas.AlertTemplate(**item))
|
|
4335
|
+
return results
|
|
4336
|
+
|
|
3701
4337
|
|
|
3702
4338
|
def _as_json(obj):
|
|
3703
4339
|
fn = getattr(obj, "to_json", None)
|