mlrun 1.7.0rc15__py3-none-any.whl → 1.7.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 (73) hide show
  1. mlrun/__init__.py +10 -1
  2. mlrun/__main__.py +18 -4
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +141 -0
  5. mlrun/artifacts/__init__.py +7 -1
  6. mlrun/artifacts/base.py +28 -3
  7. mlrun/artifacts/dataset.py +8 -0
  8. mlrun/artifacts/manager.py +18 -0
  9. mlrun/artifacts/model.py +7 -0
  10. mlrun/artifacts/plots.py +13 -0
  11. mlrun/common/schemas/__init__.py +4 -2
  12. mlrun/common/schemas/alert.py +46 -4
  13. mlrun/common/schemas/api_gateway.py +4 -0
  14. mlrun/common/schemas/artifact.py +15 -0
  15. mlrun/common/schemas/auth.py +2 -0
  16. mlrun/common/schemas/model_monitoring/__init__.py +4 -1
  17. mlrun/common/schemas/model_monitoring/constants.py +16 -1
  18. mlrun/common/schemas/model_monitoring/model_endpoints.py +60 -1
  19. mlrun/common/schemas/project.py +2 -0
  20. mlrun/config.py +4 -1
  21. mlrun/datastore/datastore_profile.py +10 -7
  22. mlrun/db/base.py +23 -3
  23. mlrun/db/httpdb.py +97 -43
  24. mlrun/db/nopdb.py +20 -2
  25. mlrun/errors.py +5 -0
  26. mlrun/launcher/base.py +3 -2
  27. mlrun/lists.py +2 -0
  28. mlrun/model.py +7 -2
  29. mlrun/model_monitoring/__init__.py +1 -1
  30. mlrun/model_monitoring/applications/_application_steps.py +1 -2
  31. mlrun/model_monitoring/applications/context.py +1 -1
  32. mlrun/model_monitoring/applications/histogram_data_drift.py +64 -38
  33. mlrun/model_monitoring/db/__init__.py +2 -0
  34. mlrun/model_monitoring/db/stores/base/store.py +9 -36
  35. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +63 -110
  36. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +56 -202
  37. mlrun/model_monitoring/db/tsdb/__init__.py +71 -0
  38. mlrun/model_monitoring/db/tsdb/base.py +135 -0
  39. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  40. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  41. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +404 -0
  42. mlrun/model_monitoring/db/v3io_tsdb_reader.py +134 -0
  43. mlrun/model_monitoring/stream_processing.py +46 -210
  44. mlrun/model_monitoring/writer.py +49 -99
  45. mlrun/platforms/__init__.py +10 -9
  46. mlrun/platforms/iguazio.py +19 -200
  47. mlrun/projects/operations.py +11 -7
  48. mlrun/projects/pipelines.py +13 -76
  49. mlrun/projects/project.py +55 -14
  50. mlrun/render.py +9 -3
  51. mlrun/run.py +5 -38
  52. mlrun/runtimes/base.py +3 -3
  53. mlrun/runtimes/kubejob.py +2 -1
  54. mlrun/runtimes/nuclio/api_gateway.py +75 -9
  55. mlrun/runtimes/nuclio/function.py +8 -34
  56. mlrun/runtimes/pod.py +16 -36
  57. mlrun/runtimes/remotesparkjob.py +1 -1
  58. mlrun/runtimes/sparkjob/spark3job.py +1 -1
  59. mlrun/runtimes/utils.py +0 -38
  60. mlrun/utils/helpers.py +45 -31
  61. mlrun/utils/notifications/notification/base.py +1 -1
  62. mlrun/utils/notifications/notification/slack.py +9 -4
  63. mlrun/utils/notifications/notification/webhook.py +1 -1
  64. mlrun/utils/notifications/notification_pusher.py +15 -14
  65. mlrun/utils/version/version.json +2 -2
  66. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/METADATA +3 -2
  67. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/RECORD +71 -65
  68. mlrun/kfpops.py +0 -860
  69. mlrun/platforms/other.py +0 -305
  70. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/LICENSE +0 -0
  71. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/WHEEL +0 -0
  72. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/entry_points.txt +0 -0
  73. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/top_level.txt +0 -0
mlrun/__init__.py CHANGED
@@ -22,11 +22,16 @@ __all__ = [
22
22
  "handler",
23
23
  "ArtifactType",
24
24
  "get_secret_or_env",
25
+ "mount_v3io",
26
+ "v3io_cred",
27
+ "auto_mount",
28
+ "VolumeMount",
25
29
  ]
26
30
 
27
31
  from os import environ, path
28
32
 
29
33
  import dotenv
34
+ import mlrun_pipelines
30
35
 
31
36
  from .config import config as mlconf
32
37
  from .datastore import DataItem, store_manager
@@ -35,7 +40,6 @@ from .errors import MLRunInvalidArgumentError, MLRunNotFoundError
35
40
  from .execution import MLClientCtx
36
41
  from .model import RunObject, RunTemplate, new_task
37
42
  from .package import ArtifactType, DefaultPackager, Packager, handler
38
- from .platforms import VolumeMount, auto_mount, mount_v3io, v3io_cred
39
43
  from .projects import (
40
44
  ProjectMetadata,
41
45
  build_function,
@@ -65,6 +69,11 @@ from .utils.version import Version
65
69
 
66
70
  __version__ = Version().get()["version"]
67
71
 
72
+ VolumeMount = mlrun_pipelines.common.mounts.VolumeMount
73
+ mount_v3io = mlrun_pipelines.mounts.mount_v3io
74
+ v3io_cred = mlrun_pipelines.mounts.v3io_cred
75
+ auto_mount = mlrun_pipelines.mounts.auto_mount
76
+
68
77
 
69
78
  def get_version():
70
79
  """get current mlrun version"""
mlrun/__main__.py CHANGED
@@ -27,6 +27,7 @@ import click
27
27
  import dotenv
28
28
  import pandas as pd
29
29
  import yaml
30
+ from mlrun_pipelines.mounts import auto_mount as auto_mount_modifier
30
31
  from tabulate import tabulate
31
32
 
32
33
  import mlrun
@@ -37,7 +38,6 @@ from .config import config as mlconf
37
38
  from .db import get_run_db
38
39
  from .errors import err_to_str
39
40
  from .model import RunTemplate
40
- from .platforms import auto_mount as auto_mount_modifier
41
41
  from .projects import load_project
42
42
  from .run import (
43
43
  get_object,
@@ -466,6 +466,17 @@ def run(
466
466
  is_flag=True,
467
467
  help="ensure the project exists, if not, create project",
468
468
  )
469
+ @click.option(
470
+ "--state-file-path", default="/tmp/state", help="path to file with state data"
471
+ )
472
+ @click.option(
473
+ "--image-file-path", default="/tmp/image", help="path to file with image data"
474
+ )
475
+ @click.option(
476
+ "--full-image-file-path",
477
+ default="/tmp/fullimage",
478
+ help="path to file with full image data",
479
+ )
469
480
  def build(
470
481
  func_url,
471
482
  name,
@@ -485,6 +496,9 @@ def build(
485
496
  skip,
486
497
  env_file,
487
498
  ensure_project,
499
+ state_file_path,
500
+ image_file_path,
501
+ full_image_file_path,
488
502
  ):
489
503
  """Build a container image from code and requirements."""
490
504
 
@@ -574,12 +588,12 @@ def build(
574
588
  state = func.status.state
575
589
  image = func.spec.image
576
590
  if kfp:
577
- with open("/tmp/state", "w") as fp:
591
+ with open(state_file_path, "w") as fp:
578
592
  fp.write(state or "none")
579
593
  full_image = func.full_image_path(image) or ""
580
- with open("/tmp/image", "w") as fp:
594
+ with open(image_file_path, "w") as fp:
581
595
  fp.write(image)
582
- with open("/tmp/fullimage", "w") as fp:
596
+ with open(full_image_file_path, "w") as fp:
583
597
  fp.write(full_image)
584
598
  print("Full image path = ", full_image)
585
599
 
@@ -0,0 +1,15 @@
1
+ # Copyright 2024 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from .alert import AlertConfig
mlrun/alerts/alert.py ADDED
@@ -0,0 +1,141 @@
1
+ # Copyright 2024 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Union
16
+
17
+ import mlrun
18
+ import mlrun.common.schemas.alert as alert_constants
19
+ from mlrun.common.schemas.notification import Notification
20
+ from mlrun.model import ModelObj
21
+
22
+
23
+ class AlertConfig(ModelObj):
24
+ _dict_fields = [
25
+ "project",
26
+ "name",
27
+ "description",
28
+ "summary",
29
+ "severity",
30
+ "criteria",
31
+ "reset_policy",
32
+ "state",
33
+ ]
34
+
35
+ def __init__(
36
+ self,
37
+ project: str = None,
38
+ name: str = None,
39
+ template: Union[alert_constants.AlertTemplate, str] = None,
40
+ description: str = None,
41
+ summary: str = None,
42
+ severity: alert_constants.AlertSeverity = None,
43
+ trigger: alert_constants.AlertTrigger = None,
44
+ criteria: alert_constants.AlertCriteria = None,
45
+ reset_policy: alert_constants.ResetPolicy = None,
46
+ notifications: list[Notification] = None,
47
+ entities: alert_constants.EventEntities = None,
48
+ id: int = None,
49
+ state: alert_constants.AlertActiveState = None,
50
+ created: str = None,
51
+ count: int = None,
52
+ ):
53
+ self.project = project
54
+ self.name = name
55
+ self.description = description
56
+ self.summary = summary
57
+ self.severity = severity
58
+ self.trigger = trigger
59
+ self.criteria = criteria
60
+ self.reset_policy = reset_policy
61
+ self.notifications = notifications or []
62
+ self.entities = entities
63
+ self.id = id
64
+ self.state = state
65
+ self.created = created
66
+ self.count = count
67
+
68
+ if template:
69
+ self._apply_template(template)
70
+
71
+ def validate_required_fields(self):
72
+ if not self.project or not self.name:
73
+ raise mlrun.errors.MLRunBadRequestError("Project and name must be provided")
74
+
75
+ def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
76
+ data = super().to_dict(self._dict_fields)
77
+
78
+ data["entities"] = (
79
+ self.entities.dict()
80
+ if not isinstance(self.entities, dict)
81
+ else self.entities
82
+ )
83
+ data["notifications"] = [
84
+ notification.dict() if not isinstance(notification, dict) else notification
85
+ for notification in self.notifications
86
+ ]
87
+ data["trigger"] = (
88
+ self.trigger.dict() if not isinstance(self.trigger, dict) else self.trigger
89
+ )
90
+ return data
91
+
92
+ @classmethod
93
+ def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
94
+ new_obj = super().from_dict(struct, fields=fields)
95
+
96
+ entity_data = struct.get("entities")
97
+ if entity_data:
98
+ entity_obj = alert_constants.EventEntities.parse_obj(entity_data)
99
+ new_obj.entities = entity_obj
100
+
101
+ notifications_data = struct.get("notifications")
102
+ if notifications_data:
103
+ notifications_objs = [
104
+ Notification.parse_obj(notification_data)
105
+ for notification_data in notifications_data
106
+ ]
107
+ new_obj.notifications = notifications_objs
108
+
109
+ trigger_data = struct.get("trigger")
110
+ if trigger_data:
111
+ trigger_obj = alert_constants.AlertTrigger.parse_obj(trigger_data)
112
+ new_obj.trigger = trigger_obj
113
+
114
+ return new_obj
115
+
116
+ def with_notifications(self, notifications: list[Notification]):
117
+ if not isinstance(notifications, list) or not all(
118
+ isinstance(item, Notification) for item in notifications
119
+ ):
120
+ raise ValueError("Notifications parameter must be a list of notifications")
121
+ for notification in notifications:
122
+ self.notifications.append(notification)
123
+ return self
124
+
125
+ def with_entities(self, entities: alert_constants.EventEntities):
126
+ if not isinstance(entities, alert_constants.EventEntities):
127
+ raise ValueError("Entities parameter must be of type: EventEntities")
128
+ self.entities = entities
129
+ return self
130
+
131
+ def _apply_template(self, template):
132
+ if isinstance(template, str):
133
+ db = mlrun.get_run_db()
134
+ template = db.get_alert_template(template)
135
+
136
+ # Extract parameters from the template and apply them to the AlertConfig object
137
+ self.description = template.description
138
+ self.severity = template.severity
139
+ self.criteria = template.criteria
140
+ self.trigger = template.trigger
141
+ self.reset_policy = template.reset_policy
@@ -17,7 +17,13 @@
17
17
  # Don't remove this, used by sphinx documentation
18
18
  __all__ = ["get_model", "update_model"]
19
19
 
20
- from .base import Artifact, ArtifactMetadata, ArtifactSpec, get_artifact_meta
20
+ from .base import (
21
+ Artifact,
22
+ ArtifactMetadata,
23
+ ArtifactSpec,
24
+ DirArtifact,
25
+ get_artifact_meta,
26
+ )
21
27
  from .dataset import DatasetArtifact, TableArtifact, update_dataset_meta
22
28
  from .manager import (
23
29
  ArtifactManager,
mlrun/artifacts/base.py CHANGED
@@ -191,12 +191,30 @@ class Artifact(ModelObj):
191
191
  format=None,
192
192
  size=None,
193
193
  target_path=None,
194
- # All params up until here are legacy params for compatibility with legacy artifacts.
195
194
  project=None,
195
+ src_path: str = None,
196
+ # All params up until here are legacy params for compatibility with legacy artifacts.
197
+ # TODO: remove them in 1.9.0.
196
198
  metadata: ArtifactMetadata = None,
197
199
  spec: ArtifactSpec = None,
198
- src_path: str = None,
199
200
  ):
201
+ if (
202
+ key
203
+ or body
204
+ or viewer
205
+ or is_inline
206
+ or format
207
+ or size
208
+ or target_path
209
+ or project
210
+ or src_path
211
+ ):
212
+ warnings.warn(
213
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
214
+ "Use the metadata and spec parameters instead.",
215
+ DeprecationWarning,
216
+ )
217
+
200
218
  self._metadata = None
201
219
  self.metadata = metadata
202
220
  self._spec = None
@@ -698,11 +716,18 @@ class LinkArtifact(Artifact):
698
716
  link_iteration=None,
699
717
  link_key=None,
700
718
  link_tree=None,
701
- # All params up until here are legacy params for compatibility with legacy artifacts.
702
719
  project=None,
720
+ # All params up until here are legacy params for compatibility with legacy artifacts.
721
+ # TODO: remove them in 1.9.0.
703
722
  metadata: ArtifactMetadata = None,
704
723
  spec: LinkArtifactSpec = None,
705
724
  ):
725
+ if key or target_path or link_iteration or link_key or link_tree or project:
726
+ warnings.warn(
727
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
728
+ "Use the metadata and spec parameters instead.",
729
+ DeprecationWarning,
730
+ )
706
731
  super().__init__(
707
732
  key, target_path=target_path, project=project, metadata=metadata, spec=spec
708
733
  )
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  import os
15
15
  import pathlib
16
+ import warnings
16
17
  from io import StringIO
17
18
  from typing import Optional
18
19
 
@@ -160,6 +161,13 @@ class DatasetArtifact(Artifact):
160
161
  label_column: str = None,
161
162
  **kwargs,
162
163
  ):
164
+ if key or format or target_path:
165
+ warnings.warn(
166
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
167
+ "Use the metadata and spec parameters instead.",
168
+ DeprecationWarning,
169
+ )
170
+
163
171
  format = (format or "").lower()
164
172
  super().__init__(key, None, format=format, target_path=target_path)
165
173
  if format and format not in self.SUPPORTED_FORMATS:
@@ -16,6 +16,7 @@ import typing
16
16
  from os.path import exists, isdir
17
17
  from urllib.parse import urlparse
18
18
 
19
+ import mlrun.common.schemas.artifact
19
20
  import mlrun.config
20
21
  from mlrun.utils.helpers import (
21
22
  get_local_file_schema,
@@ -343,6 +344,23 @@ class ArtifactManager:
343
344
  project=project,
344
345
  )
345
346
 
347
+ def delete_artifact(
348
+ self,
349
+ item: Artifact,
350
+ deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
351
+ mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
352
+ ),
353
+ secrets: dict = None,
354
+ ):
355
+ self.artifact_db.del_artifact(
356
+ key=item.db_key,
357
+ project=item.project,
358
+ tag=item.tag,
359
+ tree=item.tree,
360
+ deletion_strategy=deletion_strategy,
361
+ secrets=secrets,
362
+ )
363
+
346
364
 
347
365
  def extend_artifact_path(artifact_path: str, default_artifact_path: str):
348
366
  artifact_path = str(artifact_path or "")
mlrun/artifacts/model.py CHANGED
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import tempfile
16
+ import warnings
16
17
  from os import path
17
18
  from typing import Any, Optional
18
19
 
@@ -148,6 +149,12 @@ class ModelArtifact(Artifact):
148
149
  model_dir=None,
149
150
  **kwargs,
150
151
  ):
152
+ if key or body or format or target_path:
153
+ warnings.warn(
154
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
155
+ "Use the metadata and spec parameters instead.",
156
+ DeprecationWarning,
157
+ )
151
158
  super().__init__(key, body, format=format, target_path=target_path, **kwargs)
152
159
  model_file = str(model_file or "")
153
160
  if model_file and "/" in model_file:
mlrun/artifacts/plots.py CHANGED
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  import base64
15
15
  import typing
16
+ import warnings
16
17
  from io import BytesIO
17
18
 
18
19
  import mlrun
@@ -34,6 +35,12 @@ class PlotArtifact(Artifact):
34
35
  def __init__(
35
36
  self, key=None, body=None, is_inline=False, target_path=None, title=None
36
37
  ):
38
+ if key or body or is_inline or target_path:
39
+ warnings.warn(
40
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
41
+ "Use the metadata and spec parameters instead.",
42
+ DeprecationWarning,
43
+ )
37
44
  super().__init__(key, body, format="html", target_path=target_path)
38
45
  self.metadata.description = title
39
46
 
@@ -87,6 +94,12 @@ class PlotlyArtifact(Artifact):
87
94
  :param key: Key for the artifact to be stored in the database.
88
95
  :param target_path: Path to save the artifact.
89
96
  """
97
+ if key or target_path:
98
+ warnings.warn(
99
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
100
+ "Use the metadata and spec parameters instead.",
101
+ DeprecationWarning,
102
+ )
90
103
  # Validate the plotly package:
91
104
  try:
92
105
  from plotly.graph_objs import Figure
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
16
16
 
17
- from .alert import AlertActiveState, AlertConfig, Event
17
+ from .alert import AlertActiveState, AlertConfig, AlertTemplate, Event
18
18
  from .api_gateway import (
19
19
  APIGateway,
20
20
  APIGatewayAuthenticationMode,
@@ -142,8 +142,10 @@ from .model_monitoring import (
142
142
  ModelMonitoringMode,
143
143
  ModelMonitoringStoreKinds,
144
144
  MonitoringFunctionNames,
145
+ MonitoringTSDBTables,
145
146
  PrometheusEndpoints,
146
- TimeSeriesTarget,
147
+ TimeSeriesConnector,
148
+ TSDBTarget,
147
149
  )
148
150
  from .notification import (
149
151
  Notification,
@@ -26,10 +26,10 @@ class EventEntityKind(StrEnum):
26
26
  JOB = "job"
27
27
 
28
28
 
29
- class EventEntity(pydantic.BaseModel):
29
+ class EventEntities(pydantic.BaseModel):
30
30
  kind: EventEntityKind
31
31
  project: str
32
- id: str
32
+ ids: pydantic.conlist(str, min_items=1, max_items=1)
33
33
 
34
34
 
35
35
  class EventKind(StrEnum):
@@ -48,7 +48,7 @@ _event_kind_entity_map = {
48
48
  class Event(pydantic.BaseModel):
49
49
  kind: EventKind
50
50
  timestamp: Union[str, datetime] = None # occurrence time
51
- entity: EventEntity
51
+ entity: EventEntities
52
52
  value_dict: Optional[dict] = pydantic.Field(default_factory=dict)
53
53
 
54
54
  def is_valid(self):
@@ -71,6 +71,12 @@ class AlertTrigger(pydantic.BaseModel):
71
71
  events: list[EventKind] = []
72
72
  prometheus_alert: str = None
73
73
 
74
+ def __eq__(self, other):
75
+ return (
76
+ self.prometheus_alert == other.prometheus_alert
77
+ and self.events == other.events
78
+ )
79
+
74
80
 
75
81
  class AlertCriteria(pydantic.BaseModel):
76
82
  count: Annotated[
@@ -86,6 +92,9 @@ class AlertCriteria(pydantic.BaseModel):
86
92
  ),
87
93
  ] = None
88
94
 
95
+ def __eq__(self, other):
96
+ return self.count == other.count and self.period == other.period
97
+
89
98
 
90
99
  class ResetPolicy(StrEnum):
91
100
  MANUAL = "manual"
@@ -108,7 +117,7 @@ class AlertConfig(pydantic.BaseModel):
108
117
  ]
109
118
  created: Union[str, datetime] = None
110
119
  severity: AlertSeverity
111
- entity: EventEntity
120
+ entities: EventEntities
112
121
  trigger: AlertTrigger
113
122
  criteria: Optional[AlertCriteria]
114
123
  reset_policy: ResetPolicy = ResetPolicy.MANUAL
@@ -120,3 +129,36 @@ class AlertConfig(pydantic.BaseModel):
120
129
  class AlertsModes(StrEnum):
121
130
  enabled = "enabled"
122
131
  disabled = "disabled"
132
+
133
+
134
+ class AlertTemplate(
135
+ pydantic.BaseModel
136
+ ): # Template fields that are not shared with created configs
137
+ template_id: int = None
138
+ template_name: str
139
+ template_description: Optional[str] = (
140
+ "String explaining the purpose of this template"
141
+ )
142
+
143
+ # A property that identifies templates that were created by the system and cannot be modified/deleted by the user
144
+ system_generated: bool = False
145
+
146
+ # AlertConfig fields that are pre-defined
147
+ description: Optional[str] = (
148
+ "String to be sent in the generated notifications e.g. 'Model {{ $project }}/{{ $entity }} is drifting.'"
149
+ )
150
+ severity: AlertSeverity
151
+ trigger: AlertTrigger
152
+ criteria: Optional[AlertCriteria]
153
+ reset_policy: ResetPolicy = ResetPolicy.MANUAL
154
+
155
+ # This is slightly different than __eq__ as it doesn't compare everything
156
+ def templates_differ(self, other):
157
+ return (
158
+ self.template_description != other.template_description
159
+ or self.description != other.description
160
+ or self.severity != other.severity
161
+ or self.trigger != other.trigger
162
+ or self.reset_policy != other.reset_policy
163
+ or self.criteria != other.criteria
164
+ )
@@ -23,6 +23,7 @@ import mlrun.common.types
23
23
  class APIGatewayAuthenticationMode(mlrun.common.types.StrEnum):
24
24
  basic = "basicAuth"
25
25
  none = "none"
26
+ access_key = "accessKey"
26
27
 
27
28
  @classmethod
28
29
  def from_str(cls, authentication_mode: str):
@@ -30,6 +31,8 @@ class APIGatewayAuthenticationMode(mlrun.common.types.StrEnum):
30
31
  return cls.none
31
32
  elif authentication_mode == "basicAuth":
32
33
  return cls.basic
34
+ elif authentication_mode == "accessKey":
35
+ return cls.access_key
33
36
  else:
34
37
  raise mlrun.errors.MLRunInvalidArgumentError(
35
38
  f"Authentication mode `{authentication_mode}` is not supported",
@@ -63,6 +66,7 @@ class APIGatewayUpstream(_APIGatewayBaseModel):
63
66
  kind: Optional[str] = "nucliofunction"
64
67
  nucliofunction: dict[str, str]
65
68
  percentage: Optional[int] = 0
69
+ port: Optional[int] = 0
66
70
 
67
71
 
68
72
  class APIGatewaySpec(_APIGatewayBaseModel):
@@ -93,3 +93,18 @@ class Artifact(pydantic.BaseModel):
93
93
  metadata: ArtifactMetadata
94
94
  spec: ArtifactSpec
95
95
  status: ObjectStatus
96
+
97
+
98
+ class ArtifactsDeletionStrategies(mlrun.common.types.StrEnum):
99
+ """Artifacts deletion strategies types."""
100
+
101
+ metadata_only = "metadata-only"
102
+ """Only removes the artifact db record, leaving all related artifact data in-place"""
103
+
104
+ data_optional = "data-optional"
105
+ """Delete the artifact data of the artifact as a best-effort.
106
+ If artifact data deletion fails still try to delete the artifact db record"""
107
+
108
+ data_force = "data-force"
109
+ """Delete the artifact data, and if cannot delete it fail the deletion
110
+ and don’t delete the artifact db record"""
@@ -59,6 +59,7 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
59
59
  hub_source = "hub-source"
60
60
  workflow = "workflow"
61
61
  alert = "alert"
62
+ alert_templates = "alert-templates"
62
63
  event = "event"
63
64
  datastore_profile = "datastore-profile"
64
65
  api_gateway = "api-gateway"
@@ -87,6 +88,7 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
87
88
  AuthorizationResourceTypes.run: "/projects/{project_name}/runs/{resource_name}",
88
89
  AuthorizationResourceTypes.event: "/projects/{project_name}/events/{resource_name}",
89
90
  AuthorizationResourceTypes.alert: "/projects/{project_name}/alerts/{resource_name}",
91
+ AuthorizationResourceTypes.alert_templates: "/alert-templates/{resource_name}",
90
92
  # runtime resource doesn't have an identifier, we don't need any auth granularity behind project level
91
93
  AuthorizationResourceTypes.runtime_resource: "/projects/{project_name}/runtime-resources",
92
94
  AuthorizationResourceTypes.model_endpoint: "/projects/{project_name}/model-endpoints/{resource_name}",
@@ -30,14 +30,17 @@ from .constants import (
30
30
  ModelMonitoringMode,
31
31
  ModelMonitoringStoreKinds,
32
32
  MonitoringFunctionNames,
33
+ MonitoringTSDBTables,
33
34
  ProjectSecretKeys,
34
35
  PrometheusEndpoints,
35
36
  PrometheusMetric,
36
37
  ResultData,
37
38
  SchedulingKeys,
38
- TimeSeriesTarget,
39
+ TimeSeriesConnector,
40
+ TSDBTarget,
39
41
  VersionedModel,
40
42
  WriterEvent,
43
+ WriterEventKind,
41
44
  )
42
45
  from .grafana import (
43
46
  GrafanaColumn,
@@ -156,7 +156,7 @@ class EventKeyMetrics:
156
156
  REAL_TIME = "real_time"
157
157
 
158
158
 
159
- class TimeSeriesTarget:
159
+ class TimeSeriesConnector:
160
160
  TSDB = "tsdb"
161
161
 
162
162
 
@@ -194,6 +194,7 @@ class FileTargetKind:
194
194
  LOG_STREAM = "log_stream"
195
195
  APP_RESULTS = "app_results"
196
196
  MONITORING_SCHEDULES = "monitoring_schedules"
197
+ MONITORING_APPLICATION = "monitoring_application"
197
198
 
198
199
 
199
200
  class ModelMonitoringMode(str, Enum):
@@ -228,6 +229,12 @@ class MonitoringFunctionNames(MonitoringStrEnum):
228
229
  WRITER = "model-monitoring-writer"
229
230
 
230
231
 
232
+ class MonitoringTSDBTables(MonitoringStrEnum):
233
+ APP_RESULTS = "app-results"
234
+ METRICS = "metrics"
235
+ EVENTS = "events"
236
+
237
+
231
238
  @dataclass
232
239
  class FunctionURI:
233
240
  project: str
@@ -329,6 +336,14 @@ class ControllerPolicy:
329
336
  BASE_PERIOD = "base_period"
330
337
 
331
338
 
339
+ class TSDBTarget:
340
+ V3IO_TSDB = "v3io-tsdb"
341
+ PROMETHEUS = "prometheus"
342
+ APP_RESULTS_TABLE = "app-results"
343
+ V3IO_BE = "tsdb"
344
+ V3IO_RATE = "1/s"
345
+
346
+
332
347
  class HistogramDataDriftApplicationConstants:
333
348
  NAME = "histogram-data-drift"
334
349
  GENERAL_RESULT_NAME = "general_drift"