mlrun 1.7.0rc4__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.

Files changed (235) hide show
  1. mlrun/__init__.py +11 -1
  2. mlrun/__main__.py +39 -121
  3. mlrun/{datastore/helpers.py → alerts/__init__.py} +2 -5
  4. mlrun/alerts/alert.py +248 -0
  5. mlrun/api/schemas/__init__.py +4 -3
  6. mlrun/artifacts/__init__.py +8 -3
  7. mlrun/artifacts/base.py +39 -254
  8. mlrun/artifacts/dataset.py +9 -190
  9. mlrun/artifacts/manager.py +73 -46
  10. mlrun/artifacts/model.py +30 -158
  11. mlrun/artifacts/plots.py +23 -380
  12. mlrun/common/constants.py +73 -1
  13. mlrun/common/db/sql_session.py +3 -2
  14. mlrun/common/formatters/__init__.py +21 -0
  15. mlrun/common/formatters/artifact.py +46 -0
  16. mlrun/common/formatters/base.py +113 -0
  17. mlrun/common/formatters/feature_set.py +44 -0
  18. mlrun/common/formatters/function.py +46 -0
  19. mlrun/common/formatters/pipeline.py +53 -0
  20. mlrun/common/formatters/project.py +51 -0
  21. mlrun/common/formatters/run.py +29 -0
  22. mlrun/common/helpers.py +11 -1
  23. mlrun/{runtimes → common/runtimes}/constants.py +32 -4
  24. mlrun/common/schemas/__init__.py +31 -4
  25. mlrun/common/schemas/alert.py +202 -0
  26. mlrun/common/schemas/api_gateway.py +196 -0
  27. mlrun/common/schemas/artifact.py +28 -1
  28. mlrun/common/schemas/auth.py +13 -2
  29. mlrun/common/schemas/client_spec.py +2 -1
  30. mlrun/common/schemas/common.py +7 -4
  31. mlrun/common/schemas/constants.py +3 -0
  32. mlrun/common/schemas/feature_store.py +58 -28
  33. mlrun/common/schemas/frontend_spec.py +8 -0
  34. mlrun/common/schemas/function.py +11 -0
  35. mlrun/common/schemas/hub.py +7 -9
  36. mlrun/common/schemas/model_monitoring/__init__.py +21 -4
  37. mlrun/common/schemas/model_monitoring/constants.py +136 -42
  38. mlrun/common/schemas/model_monitoring/grafana.py +9 -5
  39. mlrun/common/schemas/model_monitoring/model_endpoints.py +89 -41
  40. mlrun/common/schemas/notification.py +69 -12
  41. mlrun/{runtimes/mpijob/v1alpha1.py → common/schemas/pagination.py} +10 -13
  42. mlrun/common/schemas/pipeline.py +7 -0
  43. mlrun/common/schemas/project.py +67 -16
  44. mlrun/common/schemas/runs.py +17 -0
  45. mlrun/common/schemas/schedule.py +1 -1
  46. mlrun/common/schemas/workflow.py +10 -2
  47. mlrun/common/types.py +14 -1
  48. mlrun/config.py +233 -58
  49. mlrun/data_types/data_types.py +11 -1
  50. mlrun/data_types/spark.py +5 -4
  51. mlrun/data_types/to_pandas.py +75 -34
  52. mlrun/datastore/__init__.py +8 -10
  53. mlrun/datastore/alibaba_oss.py +131 -0
  54. mlrun/datastore/azure_blob.py +131 -43
  55. mlrun/datastore/base.py +107 -47
  56. mlrun/datastore/datastore.py +17 -7
  57. mlrun/datastore/datastore_profile.py +91 -7
  58. mlrun/datastore/dbfs_store.py +3 -7
  59. mlrun/datastore/filestore.py +1 -3
  60. mlrun/datastore/google_cloud_storage.py +92 -32
  61. mlrun/datastore/hdfs.py +5 -0
  62. mlrun/datastore/inmem.py +6 -3
  63. mlrun/datastore/redis.py +3 -2
  64. mlrun/datastore/s3.py +30 -12
  65. mlrun/datastore/snowflake_utils.py +45 -0
  66. mlrun/datastore/sources.py +274 -59
  67. mlrun/datastore/spark_utils.py +30 -0
  68. mlrun/datastore/store_resources.py +9 -7
  69. mlrun/datastore/storeytargets.py +151 -0
  70. mlrun/datastore/targets.py +387 -119
  71. mlrun/datastore/utils.py +68 -5
  72. mlrun/datastore/v3io.py +28 -50
  73. mlrun/db/auth_utils.py +152 -0
  74. mlrun/db/base.py +245 -20
  75. mlrun/db/factory.py +1 -4
  76. mlrun/db/httpdb.py +909 -231
  77. mlrun/db/nopdb.py +279 -14
  78. mlrun/errors.py +35 -5
  79. mlrun/execution.py +111 -38
  80. mlrun/feature_store/__init__.py +0 -2
  81. mlrun/feature_store/api.py +46 -53
  82. mlrun/feature_store/common.py +6 -11
  83. mlrun/feature_store/feature_set.py +48 -23
  84. mlrun/feature_store/feature_vector.py +13 -2
  85. mlrun/feature_store/ingestion.py +7 -6
  86. mlrun/feature_store/retrieval/base.py +9 -4
  87. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  88. mlrun/feature_store/retrieval/job.py +13 -4
  89. mlrun/feature_store/retrieval/local_merger.py +2 -0
  90. mlrun/feature_store/retrieval/spark_merger.py +24 -32
  91. mlrun/feature_store/steps.py +38 -19
  92. mlrun/features.py +6 -14
  93. mlrun/frameworks/_common/plan.py +3 -3
  94. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
  95. mlrun/frameworks/_ml_common/plan.py +1 -1
  96. mlrun/frameworks/auto_mlrun/auto_mlrun.py +2 -2
  97. mlrun/frameworks/lgbm/__init__.py +1 -1
  98. mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
  99. mlrun/frameworks/lgbm/model_handler.py +1 -1
  100. mlrun/frameworks/parallel_coordinates.py +4 -4
  101. mlrun/frameworks/pytorch/__init__.py +2 -2
  102. mlrun/frameworks/sklearn/__init__.py +1 -1
  103. mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
  104. mlrun/frameworks/tf_keras/__init__.py +5 -2
  105. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
  106. mlrun/frameworks/tf_keras/mlrun_interface.py +2 -2
  107. mlrun/frameworks/xgboost/__init__.py +1 -1
  108. mlrun/k8s_utils.py +57 -12
  109. mlrun/launcher/__init__.py +1 -1
  110. mlrun/launcher/base.py +6 -5
  111. mlrun/launcher/client.py +13 -11
  112. mlrun/launcher/factory.py +1 -1
  113. mlrun/launcher/local.py +15 -5
  114. mlrun/launcher/remote.py +10 -3
  115. mlrun/lists.py +6 -2
  116. mlrun/model.py +297 -48
  117. mlrun/model_monitoring/__init__.py +1 -1
  118. mlrun/model_monitoring/api.py +152 -357
  119. mlrun/model_monitoring/applications/__init__.py +10 -0
  120. mlrun/model_monitoring/applications/_application_steps.py +190 -0
  121. mlrun/model_monitoring/applications/base.py +108 -0
  122. mlrun/model_monitoring/applications/context.py +341 -0
  123. mlrun/model_monitoring/{evidently_application.py → applications/evidently_base.py} +27 -22
  124. mlrun/model_monitoring/applications/histogram_data_drift.py +227 -91
  125. mlrun/model_monitoring/applications/results.py +99 -0
  126. mlrun/model_monitoring/controller.py +130 -303
  127. mlrun/model_monitoring/{stores/models/sqlite.py → db/__init__.py} +5 -10
  128. mlrun/model_monitoring/db/stores/__init__.py +136 -0
  129. mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
  130. mlrun/model_monitoring/db/stores/base/store.py +213 -0
  131. mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
  132. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
  133. mlrun/model_monitoring/db/stores/sqldb/models/base.py +190 -0
  134. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +103 -0
  135. mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
  136. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +659 -0
  137. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
  138. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +726 -0
  139. mlrun/model_monitoring/db/tsdb/__init__.py +105 -0
  140. mlrun/model_monitoring/db/tsdb/base.py +448 -0
  141. mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
  142. mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
  143. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +298 -0
  144. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +42 -0
  145. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +522 -0
  146. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  147. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +158 -0
  148. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +849 -0
  149. mlrun/model_monitoring/features_drift_table.py +34 -22
  150. mlrun/model_monitoring/helpers.py +177 -39
  151. mlrun/model_monitoring/model_endpoint.py +3 -2
  152. mlrun/model_monitoring/stream_processing.py +165 -398
  153. mlrun/model_monitoring/tracking_policy.py +7 -1
  154. mlrun/model_monitoring/writer.py +161 -125
  155. mlrun/package/packagers/default_packager.py +2 -2
  156. mlrun/package/packagers_manager.py +1 -0
  157. mlrun/package/utils/_formatter.py +2 -2
  158. mlrun/platforms/__init__.py +11 -10
  159. mlrun/platforms/iguazio.py +67 -228
  160. mlrun/projects/__init__.py +6 -1
  161. mlrun/projects/operations.py +47 -20
  162. mlrun/projects/pipelines.py +396 -249
  163. mlrun/projects/project.py +1176 -406
  164. mlrun/render.py +28 -22
  165. mlrun/run.py +208 -181
  166. mlrun/runtimes/__init__.py +76 -11
  167. mlrun/runtimes/base.py +54 -24
  168. mlrun/runtimes/daskjob.py +9 -2
  169. mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
  170. mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
  171. mlrun/runtimes/funcdoc.py +1 -29
  172. mlrun/runtimes/kubejob.py +34 -128
  173. mlrun/runtimes/local.py +39 -10
  174. mlrun/runtimes/mpijob/__init__.py +0 -20
  175. mlrun/runtimes/mpijob/abstract.py +8 -8
  176. mlrun/runtimes/mpijob/v1.py +1 -1
  177. mlrun/runtimes/nuclio/__init__.py +1 -0
  178. mlrun/runtimes/nuclio/api_gateway.py +769 -0
  179. mlrun/runtimes/nuclio/application/__init__.py +15 -0
  180. mlrun/runtimes/nuclio/application/application.py +758 -0
  181. mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
  182. mlrun/runtimes/nuclio/function.py +188 -68
  183. mlrun/runtimes/nuclio/serving.py +57 -60
  184. mlrun/runtimes/pod.py +191 -58
  185. mlrun/runtimes/remotesparkjob.py +11 -8
  186. mlrun/runtimes/sparkjob/spark3job.py +17 -18
  187. mlrun/runtimes/utils.py +40 -73
  188. mlrun/secrets.py +6 -2
  189. mlrun/serving/__init__.py +8 -1
  190. mlrun/serving/remote.py +2 -3
  191. mlrun/serving/routers.py +89 -64
  192. mlrun/serving/server.py +54 -26
  193. mlrun/serving/states.py +187 -56
  194. mlrun/serving/utils.py +19 -11
  195. mlrun/serving/v2_serving.py +136 -63
  196. mlrun/track/tracker.py +2 -1
  197. mlrun/track/trackers/mlflow_tracker.py +5 -0
  198. mlrun/utils/async_http.py +26 -6
  199. mlrun/utils/db.py +18 -0
  200. mlrun/utils/helpers.py +375 -105
  201. mlrun/utils/http.py +2 -2
  202. mlrun/utils/logger.py +75 -9
  203. mlrun/utils/notifications/notification/__init__.py +14 -10
  204. mlrun/utils/notifications/notification/base.py +48 -0
  205. mlrun/utils/notifications/notification/console.py +2 -0
  206. mlrun/utils/notifications/notification/git.py +24 -1
  207. mlrun/utils/notifications/notification/ipython.py +2 -0
  208. mlrun/utils/notifications/notification/slack.py +96 -21
  209. mlrun/utils/notifications/notification/webhook.py +63 -2
  210. mlrun/utils/notifications/notification_pusher.py +146 -16
  211. mlrun/utils/regex.py +9 -0
  212. mlrun/utils/retryer.py +3 -2
  213. mlrun/utils/v3io_clients.py +2 -3
  214. mlrun/utils/version/version.json +2 -2
  215. mlrun-1.7.2.dist-info/METADATA +390 -0
  216. mlrun-1.7.2.dist-info/RECORD +351 -0
  217. {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/WHEEL +1 -1
  218. mlrun/feature_store/retrieval/conversion.py +0 -271
  219. mlrun/kfpops.py +0 -868
  220. mlrun/model_monitoring/application.py +0 -310
  221. mlrun/model_monitoring/batch.py +0 -974
  222. mlrun/model_monitoring/controller_handler.py +0 -37
  223. mlrun/model_monitoring/prometheus.py +0 -216
  224. mlrun/model_monitoring/stores/__init__.py +0 -111
  225. mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -574
  226. mlrun/model_monitoring/stores/model_endpoint_store.py +0 -145
  227. mlrun/model_monitoring/stores/models/__init__.py +0 -27
  228. mlrun/model_monitoring/stores/models/base.py +0 -84
  229. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -382
  230. mlrun/platforms/other.py +0 -305
  231. mlrun-1.7.0rc4.dist-info/METADATA +0 -269
  232. mlrun-1.7.0rc4.dist-info/RECORD +0 -321
  233. {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/LICENSE +0 -0
  234. {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/entry_points.txt +0 -0
  235. {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,202 @@
1
+ # Copyright 2023 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 datetime import datetime
16
+ from typing import Annotated, Optional, Union
17
+
18
+ import pydantic
19
+
20
+ from mlrun.common.schemas.notification import Notification
21
+ from mlrun.common.types import StrEnum
22
+
23
+
24
+ class EventEntityKind(StrEnum):
25
+ MODEL_ENDPOINT_RESULT = "model-endpoint-result"
26
+ MODEL_MONITORING_APPLICATION = "model-monitoring-application"
27
+ JOB = "job"
28
+
29
+
30
+ class EventEntities(pydantic.BaseModel):
31
+ kind: EventEntityKind
32
+ project: str
33
+ ids: pydantic.conlist(str, min_items=1, max_items=1)
34
+
35
+
36
+ class EventKind(StrEnum):
37
+ DATA_DRIFT_DETECTED = "data-drift-detected"
38
+ DATA_DRIFT_SUSPECTED = "data-drift-suspected"
39
+ CONCEPT_DRIFT_DETECTED = "concept-drift-detected"
40
+ CONCEPT_DRIFT_SUSPECTED = "concept-drift-suspected"
41
+ MODEL_PERFORMANCE_DETECTED = "model-performance-detected"
42
+ MODEL_PERFORMANCE_SUSPECTED = "model-performance-suspected"
43
+ SYSTEM_PERFORMANCE_DETECTED = "system-performance-detected"
44
+ SYSTEM_PERFORMANCE_SUSPECTED = "system-performance-suspected"
45
+ MM_APP_ANOMALY_DETECTED = "mm-app-anomaly-detected"
46
+ MM_APP_ANOMALY_SUSPECTED = "mm-app-anomaly-suspected"
47
+ MM_APP_FAILED = "mm-app-failed"
48
+ FAILED = "failed"
49
+
50
+
51
+ _event_kind_entity_map = {
52
+ EventKind.DATA_DRIFT_SUSPECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
53
+ EventKind.DATA_DRIFT_DETECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
54
+ EventKind.CONCEPT_DRIFT_DETECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
55
+ EventKind.CONCEPT_DRIFT_SUSPECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
56
+ EventKind.MODEL_PERFORMANCE_DETECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
57
+ EventKind.MODEL_PERFORMANCE_SUSPECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
58
+ EventKind.SYSTEM_PERFORMANCE_DETECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
59
+ EventKind.SYSTEM_PERFORMANCE_SUSPECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
60
+ EventKind.MM_APP_ANOMALY_DETECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
61
+ EventKind.MM_APP_ANOMALY_SUSPECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
62
+ EventKind.MM_APP_FAILED: [EventEntityKind.MODEL_MONITORING_APPLICATION],
63
+ EventKind.FAILED: [EventEntityKind.JOB],
64
+ }
65
+
66
+
67
+ class Event(pydantic.BaseModel):
68
+ kind: EventKind
69
+ timestamp: Union[str, datetime] = None # occurrence time
70
+ entity: EventEntities
71
+ value_dict: Optional[dict] = pydantic.Field(default_factory=dict)
72
+
73
+ def is_valid(self):
74
+ return self.entity.kind in _event_kind_entity_map[self.kind]
75
+
76
+
77
+ class AlertActiveState(StrEnum):
78
+ ACTIVE = "active"
79
+ INACTIVE = "inactive"
80
+
81
+
82
+ class AlertSeverity(StrEnum):
83
+ LOW = "low"
84
+ MEDIUM = "medium"
85
+ HIGH = "high"
86
+
87
+
88
+ # what should trigger the alert. must be either event (at least 1), or prometheus query
89
+ class AlertTrigger(pydantic.BaseModel):
90
+ events: list[EventKind] = []
91
+ prometheus_alert: str = None
92
+
93
+ def __eq__(self, other):
94
+ return (
95
+ self.prometheus_alert == other.prometheus_alert
96
+ and self.events == other.events
97
+ )
98
+
99
+
100
+ class AlertCriteria(pydantic.BaseModel):
101
+ count: Annotated[
102
+ int,
103
+ pydantic.Field(
104
+ description="Number of events to wait until notification is sent"
105
+ ),
106
+ ] = 1
107
+ period: Annotated[
108
+ str,
109
+ pydantic.Field(
110
+ description="Time period during which event occurred. e.g. 1d, 3h, 5m, 15s"
111
+ ),
112
+ ] = None
113
+
114
+ def __eq__(self, other):
115
+ return self.count == other.count and self.period == other.period
116
+
117
+
118
+ class ResetPolicy(StrEnum):
119
+ MANUAL = "manual"
120
+ AUTO = "auto"
121
+
122
+
123
+ class AlertNotification(pydantic.BaseModel):
124
+ notification: Notification
125
+ cooldown_period: Annotated[
126
+ str,
127
+ pydantic.Field(
128
+ description="Period during which notifications "
129
+ "will not be sent after initial send. The format of this would be in time."
130
+ " e.g. 1d, 3h, 5m, 15s"
131
+ ),
132
+ ] = None
133
+
134
+
135
+ class AlertConfig(pydantic.BaseModel):
136
+ project: str
137
+ id: int = None
138
+ name: str
139
+ description: Optional[str] = ""
140
+ summary: Annotated[
141
+ str,
142
+ pydantic.Field(
143
+ description=(
144
+ "String to be sent in the notifications generated."
145
+ "e.g. 'Model {{project}}/{{entity}} is drifting.'"
146
+ "Supported variables: project, entity, name"
147
+ )
148
+ ),
149
+ ]
150
+ created: Union[str, datetime] = None
151
+ severity: AlertSeverity
152
+ entities: EventEntities
153
+ trigger: AlertTrigger
154
+ criteria: Optional[AlertCriteria]
155
+ reset_policy: ResetPolicy = ResetPolicy.AUTO
156
+ notifications: pydantic.conlist(AlertNotification, min_items=1)
157
+ state: AlertActiveState = AlertActiveState.INACTIVE
158
+ count: Optional[int] = 0
159
+
160
+ def get_raw_notifications(self) -> list[Notification]:
161
+ return [
162
+ alert_notification.notification for alert_notification in self.notifications
163
+ ]
164
+
165
+
166
+ class AlertsModes(StrEnum):
167
+ enabled = "enabled"
168
+ disabled = "disabled"
169
+
170
+
171
+ class AlertTemplate(
172
+ pydantic.BaseModel
173
+ ): # Template fields that are not shared with created configs
174
+ template_id: int = None
175
+ template_name: str
176
+ template_description: Optional[str] = (
177
+ "String explaining the purpose of this template"
178
+ )
179
+
180
+ # A property that identifies templates that were created by the system and cannot be modified/deleted by the user
181
+ system_generated: bool = False
182
+
183
+ # AlertConfig fields that are pre-defined
184
+ summary: Optional[str] = (
185
+ "String to be sent in the generated notifications e.g. 'Model {{project}}/{{entity}} is drifting.'"
186
+ "See AlertConfig.summary description"
187
+ )
188
+ severity: AlertSeverity
189
+ trigger: AlertTrigger
190
+ criteria: Optional[AlertCriteria]
191
+ reset_policy: ResetPolicy = ResetPolicy.AUTO
192
+
193
+ # This is slightly different than __eq__ as it doesn't compare everything
194
+ def templates_differ(self, other):
195
+ return (
196
+ self.template_description != other.template_description
197
+ or self.summary != other.summary
198
+ or self.severity != other.severity
199
+ or self.trigger != other.trigger
200
+ or self.reset_policy != other.reset_policy
201
+ or self.criteria != other.criteria
202
+ )
@@ -0,0 +1,196 @@
1
+ # Copyright 2023 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
+ import typing
16
+ from typing import Optional
17
+
18
+ import pydantic
19
+
20
+ import mlrun.common.constants as mlrun_constants
21
+ import mlrun.common.types
22
+ from mlrun.common.constants import MLRUN_FUNCTIONS_ANNOTATION
23
+ from mlrun.common.helpers import generate_api_gateway_name
24
+
25
+
26
+ class APIGatewayAuthenticationMode(mlrun.common.types.StrEnum):
27
+ basic = "basicAuth"
28
+ none = "none"
29
+ access_key = "accessKey"
30
+
31
+ @classmethod
32
+ def from_str(cls, authentication_mode: str):
33
+ if authentication_mode == "none":
34
+ return cls.none
35
+ elif authentication_mode == "basicAuth":
36
+ return cls.basic
37
+ elif authentication_mode == "accessKey":
38
+ return cls.access_key
39
+ else:
40
+ raise mlrun.errors.MLRunInvalidArgumentError(
41
+ f"Authentication mode `{authentication_mode}` is not supported",
42
+ )
43
+
44
+
45
+ class APIGatewayState(mlrun.common.types.StrEnum):
46
+ none = ""
47
+ ready = "ready"
48
+ error = "error"
49
+ waiting_for_provisioning = "waitingForProvisioning"
50
+
51
+
52
+ class _APIGatewayBaseModel(pydantic.BaseModel):
53
+ class Config:
54
+ extra = pydantic.Extra.allow
55
+
56
+
57
+ class APIGatewayMetadata(_APIGatewayBaseModel):
58
+ name: str
59
+ namespace: Optional[str]
60
+ labels: Optional[dict] = {}
61
+ annotations: Optional[dict] = {}
62
+
63
+
64
+ class APIGatewayBasicAuth(_APIGatewayBaseModel):
65
+ username: str
66
+ password: str
67
+
68
+
69
+ class APIGatewayUpstream(_APIGatewayBaseModel):
70
+ kind: Optional[str] = "nucliofunction"
71
+ nucliofunction: dict[str, str]
72
+ percentage: Optional[int] = 0
73
+ port: Optional[int] = 0
74
+
75
+
76
+ class APIGatewaySpec(_APIGatewayBaseModel):
77
+ name: str
78
+ description: Optional[str]
79
+ path: Optional[str] = "/"
80
+ authenticationMode: Optional[APIGatewayAuthenticationMode] = ( # noqa: N815 - for compatibility with Nuclio https://github.com/nuclio/nuclio/blob/672b8e36f9edd6e42b4685ec1d27cabae3c5f045/pkg/platform/types.go#L476
81
+ APIGatewayAuthenticationMode.none
82
+ )
83
+ upstreams: list[APIGatewayUpstream]
84
+ authentication: Optional[dict[str, Optional[APIGatewayBasicAuth]]]
85
+ host: Optional[str]
86
+
87
+
88
+ class APIGatewayStatus(_APIGatewayBaseModel):
89
+ name: Optional[str]
90
+ state: Optional[APIGatewayState]
91
+
92
+
93
+ class APIGateway(_APIGatewayBaseModel):
94
+ metadata: APIGatewayMetadata
95
+ spec: APIGatewaySpec
96
+ status: Optional[APIGatewayStatus]
97
+
98
+ def get_function_names(self):
99
+ return [
100
+ upstream.nucliofunction.get("name")
101
+ for upstream in self.spec.upstreams
102
+ if upstream.nucliofunction.get("name")
103
+ ]
104
+
105
+ def get_invoke_url(self):
106
+ if self.spec.host and self.spec.path:
107
+ return f"{self.spec.host.rstrip('/')}/{self.spec.path.lstrip('/')}".rstrip(
108
+ "/"
109
+ )
110
+ return self.spec.host.rstrip("/")
111
+
112
+ def enrich_mlrun_names(self):
113
+ self._enrich_api_gateway_mlrun_name()
114
+ self._enrich_mlrun_function_names()
115
+ return self
116
+
117
+ def replace_nuclio_names_with_mlrun_names(self):
118
+ self._replace_nuclio_api_gateway_name_with_mlrun_name()
119
+ self._replace_nuclio_function_names_with_mlrun_names()
120
+ return self
121
+
122
+ def _replace_nuclio_function_names_with_mlrun_names(self):
123
+ # replace function names from nuclio names to mlrun names
124
+ # and adds mlrun function URI's to an api gateway annotations
125
+ # so when we then get api gateway entity from nuclio, we are able to get mlrun function names
126
+ mlrun_functions = self.metadata.annotations.get(MLRUN_FUNCTIONS_ANNOTATION)
127
+ if mlrun_functions:
128
+ mlrun_function_uris = (
129
+ mlrun_functions.split("&")
130
+ if "&" in mlrun_functions
131
+ else [mlrun_functions]
132
+ )
133
+ if len(mlrun_function_uris) != len(self.spec.upstreams):
134
+ raise mlrun.errors.MLRunValueError(
135
+ "Error when translating nuclio names to mlrun names in api gateway:"
136
+ " number of functions doesn't match the mlrun functions in annotation"
137
+ )
138
+ for i in range(len(mlrun_function_uris)):
139
+ self.spec.upstreams[i].nucliofunction["name"] = mlrun_function_uris[i]
140
+ return self
141
+
142
+ def _replace_nuclio_api_gateway_name_with_mlrun_name(self):
143
+ # replace api gateway name
144
+ # in Nuclio, api gateways are named as `<project>-<mlrun-api-gateway-name>`
145
+ # remove the project prefix from the name if it exists
146
+ project_name = self.metadata.labels.get(
147
+ mlrun_constants.MLRunInternalLabels.nuclio_project_name
148
+ )
149
+ if project_name and self.spec.name.startswith(f"{project_name}-"):
150
+ self.spec.name = self.spec.name[len(project_name) + 1 :]
151
+ self.metadata.name = self.spec.name
152
+ return self
153
+
154
+ def _enrich_mlrun_function_names(self):
155
+ # enrich mlrun names with nuclio prefixes
156
+ # and add mlrun function's URIs to Nuclio function annotations
157
+ upstream_with_nuclio_names = []
158
+ mlrun_function_uris = []
159
+ for upstream in self.spec.upstreams:
160
+ uri = upstream.nucliofunction.get("name")
161
+ project, function_name, tag, _ = (
162
+ mlrun.common.helpers.parse_versioned_object_uri(uri)
163
+ )
164
+ upstream.nucliofunction["name"] = (
165
+ mlrun.runtimes.nuclio.function.get_fullname(function_name, project, tag)
166
+ )
167
+
168
+ upstream_with_nuclio_names.append(upstream)
169
+ mlrun_function_uris.append(uri)
170
+
171
+ self.spec.upstreams = upstream_with_nuclio_names
172
+ if len(mlrun_function_uris) == 1:
173
+ self.metadata.annotations[MLRUN_FUNCTIONS_ANNOTATION] = mlrun_function_uris[
174
+ 0
175
+ ]
176
+ elif len(mlrun_function_uris) == 2:
177
+ self.metadata.annotations[MLRUN_FUNCTIONS_ANNOTATION] = "&".join(
178
+ mlrun_function_uris
179
+ )
180
+ return self
181
+
182
+ def _enrich_api_gateway_mlrun_name(self):
183
+ # replace api gateway name
184
+ # in Nuclio, api gateways are named as `<project>-<mlrun-api-gateway-name>`
185
+ # add the project prefix to the name
186
+ project_name = self.metadata.labels.get(
187
+ mlrun_constants.MLRunInternalLabels.nuclio_project_name
188
+ )
189
+ if project_name:
190
+ self.spec.name = generate_api_gateway_name(project_name, self.spec.name)
191
+ self.metadata.name = self.spec.name
192
+ return self
193
+
194
+
195
+ class APIGatewaysOutput(_APIGatewayBaseModel):
196
+ api_gateways: typing.Optional[dict[str, APIGateway]] = {}
@@ -15,6 +15,7 @@
15
15
  import typing
16
16
 
17
17
  import pydantic
18
+ from deprecated import deprecated
18
19
 
19
20
  import mlrun.common.types
20
21
 
@@ -46,6 +47,12 @@ class ArtifactCategories(mlrun.common.types.StrEnum):
46
47
  True,
47
48
  )
48
49
 
50
+ @classmethod
51
+ def from_kind(cls, kind: str) -> "ArtifactCategories":
52
+ if kind in [cls.model.value, cls.dataset.value]:
53
+ return cls(kind)
54
+ return cls.other
55
+
49
56
 
50
57
  class ArtifactIdentifier(pydantic.BaseModel):
51
58
  # artifact kind
@@ -58,8 +65,13 @@ class ArtifactIdentifier(pydantic.BaseModel):
58
65
  # hash: typing.Optional[str]
59
66
 
60
67
 
68
+ @deprecated(
69
+ version="1.7.0",
70
+ reason="mlrun.common.schemas.ArtifactsFormat is deprecated and will be removed in 1.9.0. "
71
+ "Use mlrun.common.formatters.ArtifactFormat instead.",
72
+ category=FutureWarning,
73
+ )
61
74
  class ArtifactsFormat(mlrun.common.types.StrEnum):
62
- # TODO: add a format that returns a minimal response
63
75
  full = "full"
64
76
 
65
77
 
@@ -93,3 +105,18 @@ class Artifact(pydantic.BaseModel):
93
105
  metadata: ArtifactMetadata
94
106
  spec: ArtifactSpec
95
107
  status: ObjectStatus
108
+
109
+
110
+ class ArtifactsDeletionStrategies(mlrun.common.types.StrEnum):
111
+ """Artifacts deletion strategies types."""
112
+
113
+ metadata_only = "metadata-only"
114
+ """Only removes the artifact db record, leaving all related artifact data in-place"""
115
+
116
+ data_optional = "data-optional"
117
+ """Delete the artifact data of the artifact as a best-effort.
118
+ If artifact data deletion fails still try to delete the artifact db record"""
119
+
120
+ data_force = "data-force"
121
+ """Delete the artifact data, and if cannot delete it fail the deletion
122
+ and don’t delete the artifact db record"""
@@ -58,8 +58,12 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
58
58
  pipeline = "pipeline"
59
59
  hub_source = "hub-source"
60
60
  workflow = "workflow"
61
+ alert = "alert"
62
+ alert_templates = "alert-templates"
63
+ event = "event"
61
64
  datastore_profile = "datastore-profile"
62
- api_gateways = "api-gateways"
65
+ api_gateway = "api-gateway"
66
+ project_summaries = "project-summaries"
63
67
 
64
68
  def to_resource_string(
65
69
  self,
@@ -69,6 +73,7 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
69
73
  return {
70
74
  # project is the resource itself, so no need for both resource_name and project_name
71
75
  AuthorizationResourceTypes.project: "/projects/{project_name}",
76
+ AuthorizationResourceTypes.project_summaries: "/projects/{project_name}/project-summaries/{resource_name}",
72
77
  AuthorizationResourceTypes.function: "/projects/{project_name}/functions/{resource_name}",
73
78
  AuthorizationResourceTypes.artifact: "/projects/{project_name}/artifacts/{resource_name}",
74
79
  AuthorizationResourceTypes.project_background_task: (
@@ -83,6 +88,9 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
83
88
  AuthorizationResourceTypes.schedule: "/projects/{project_name}/schedules/{resource_name}",
84
89
  AuthorizationResourceTypes.secret: "/projects/{project_name}/secrets/{resource_name}",
85
90
  AuthorizationResourceTypes.run: "/projects/{project_name}/runs/{resource_name}",
91
+ AuthorizationResourceTypes.event: "/projects/{project_name}/events/{resource_name}",
92
+ AuthorizationResourceTypes.alert: "/projects/{project_name}/alerts/{resource_name}",
93
+ AuthorizationResourceTypes.alert_templates: "/alert-templates/{resource_name}",
86
94
  # runtime resource doesn't have an identifier, we don't need any auth granularity behind project level
87
95
  AuthorizationResourceTypes.runtime_resource: "/projects/{project_name}/runtime-resources",
88
96
  AuthorizationResourceTypes.model_endpoint: "/projects/{project_name}/model-endpoints/{resource_name}",
@@ -94,7 +102,7 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
94
102
  AuthorizationResourceTypes.hub_source: "/marketplace/sources",
95
103
  # workflow define how to run a pipeline and can be considered as the specification of a pipeline.
96
104
  AuthorizationResourceTypes.workflow: "/projects/{project_name}/workflows/{resource_name}",
97
- AuthorizationResourceTypes.api_gateways: "/projects/{project_name}/api-gateways",
105
+ AuthorizationResourceTypes.api_gateway: "/projects/{project_name}/api-gateways/{resource_name}",
98
106
  }[self].format(project_name=project_name, resource_name=resource_name)
99
107
 
100
108
 
@@ -133,6 +141,9 @@ class AuthInfo(pydantic.BaseModel):
133
141
  member_ids.extend(self.user_group_ids)
134
142
  return member_ids
135
143
 
144
+ def get_session(self) -> str:
145
+ return self.data_session or self.session
146
+
136
147
 
137
148
  class Credentials(pydantic.BaseModel):
138
149
  access_key: typing.Optional[str]
@@ -57,8 +57,8 @@ class ClientSpec(pydantic.BaseModel):
57
57
  redis_url: typing.Optional[str]
58
58
  redis_type: typing.Optional[str]
59
59
  sql_url: typing.Optional[str]
60
- model_endpoint_monitoring_store_type: typing.Optional[str]
61
60
  model_endpoint_monitoring_endpoint_store_connection: typing.Optional[str]
61
+ model_monitoring_tsdb_connection: typing.Optional[str]
62
62
  ce: typing.Optional[dict]
63
63
  # not passing them as one object as it possible client user would like to override only one of the params
64
64
  calculate_artifact_hash: typing.Optional[str]
@@ -66,3 +66,4 @@ class ClientSpec(pydantic.BaseModel):
66
66
  logs: typing.Optional[dict]
67
67
  packagers: typing.Optional[dict]
68
68
  external_platform_tracking: typing.Optional[dict]
69
+ alerts_mode: typing.Optional[str]
@@ -11,16 +11,16 @@
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
15
  import typing
16
16
 
17
17
  import pydantic
18
18
 
19
19
 
20
20
  class ImageBuilder(pydantic.BaseModel):
21
- functionSourceCode: typing.Optional[str] = None
22
- codeEntryType: typing.Optional[str] = None
23
- codeEntryAttributes: typing.Optional[str] = None
21
+ functionSourceCode: typing.Optional[str] = None # noqa: N815
22
+ codeEntryType: typing.Optional[str] = None # noqa: N815
23
+ codeEntryAttributes: typing.Optional[str] = None # noqa: N815
24
24
  source: typing.Optional[str] = None
25
25
  code_origin: typing.Optional[str] = None
26
26
  origin_filename: typing.Optional[str] = None
@@ -38,3 +38,6 @@ class ImageBuilder(pydantic.BaseModel):
38
38
  build_pod: typing.Optional[str] = None
39
39
  requirements: typing.Optional[list] = None
40
40
  source_code_target_dir: typing.Optional[str] = None
41
+
42
+ class Config:
43
+ extra = pydantic.Extra.allow
@@ -120,10 +120,13 @@ class FeatureStorePartitionByField(mlrun.common.types.StrEnum):
120
120
 
121
121
  class RunPartitionByField(mlrun.common.types.StrEnum):
122
122
  name = "name" # Supported for runs objects
123
+ project_and_name = "project_and_name" # Supported for runs objects
123
124
 
124
125
  def to_partition_by_db_field(self, db_cls):
125
126
  if self.value == RunPartitionByField.name:
126
127
  return db_cls.name
128
+ elif self.value == RunPartitionByField.project_and_name:
129
+ return db_cls.project, db_cls.name
127
130
  else:
128
131
  raise mlrun.errors.MLRunInvalidArgumentError(
129
132
  f"Unknown group by field: {self.value}"