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.
- 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 -1
- 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 +31 -4
- mlrun/common/schemas/alert.py +202 -0
- mlrun/common/schemas/api_gateway.py +196 -0
- mlrun/common/schemas/artifact.py +28 -1
- mlrun/common/schemas/auth.py +13 -2
- 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 +233 -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 +387 -119
- mlrun/datastore/utils.py +68 -5
- mlrun/datastore/v3io.py +28 -50
- mlrun/db/auth_utils.py +152 -0
- mlrun/db/base.py +245 -20
- mlrun/db/factory.py +1 -4
- mlrun/db/httpdb.py +909 -231
- mlrun/db/nopdb.py +279 -14
- 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 +1176 -406
- mlrun/render.py +28 -22
- mlrun/run.py +208 -181
- mlrun/runtimes/__init__.py +76 -11
- mlrun/runtimes/base.py +54 -24
- 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/__init__.py +1 -0
- mlrun/runtimes/nuclio/api_gateway.py +769 -0
- 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.0rc4.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.0rc4.dist-info/METADATA +0 -269
- mlrun-1.7.0rc4.dist-info/RECORD +0 -321
- {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc4.dist-info → mlrun-1.7.2.dist-info}/entry_points.txt +0 -0
- {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]] = {}
|
mlrun/common/schemas/artifact.py
CHANGED
|
@@ -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"""
|
mlrun/common/schemas/auth.py
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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]
|
mlrun/common/schemas/common.py
CHANGED
|
@@ -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}"
|