Skip to content

Commit 9b591da

Browse files
authored
[Model Monitoring] Enforce user to define credentials (mlrun#5827)
1 parent 8916118 commit 9b591da

File tree

29 files changed

+757
-245
lines changed

29 files changed

+757
-245
lines changed

automation/system_test/prepare.py

+5
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,11 @@ def _enrich_env(self):
395395
)
396396
self._env_config["V3IO_API"] = f"https://{v3io_api_host}"
397397
self._env_config["MLRUN_DBPATH"] = f"https://{mlrun_api_url}"
398+
self._env_config[
399+
"MLRUN_MODEL_ENDPOINT_MONITORING__ENDPOINT_STORE_CONNECTION"
400+
] = "v3io"
401+
self._env_config["MLRUN_MODEL_ENDPOINT_MONITORING__TSDB_CONNECTION"] = "v3io"
402+
self._env_config["MLRUN_MODEL_ENDPOINT_MONITORING__STREAM_CONNECTION"] = "v3io"
398403

399404
def _install_dev_utilities(self):
400405
list_uninstall = [

mlrun/common/schemas/model_monitoring/constants.py

+20-9
Original file line numberDiff line numberDiff line change
@@ -158,19 +158,36 @@ class EventKeyMetrics:
158158
REAL_TIME = "real_time"
159159

160160

161-
class ModelEndpointTarget:
161+
class ModelEndpointTarget(MonitoringStrEnum):
162162
V3IO_NOSQL = "v3io-nosql"
163163
SQL = "sql"
164164

165165

166+
class StreamKind(MonitoringStrEnum):
167+
V3IO_STREAM = "v3io_stream"
168+
KAFKA = "kafka"
169+
170+
171+
class TSDBTarget(MonitoringStrEnum):
172+
V3IO_TSDB = "v3io-tsdb"
173+
TDEngine = "tdengine"
174+
PROMETHEUS = "prometheus"
175+
176+
166177
class ProjectSecretKeys:
167178
ENDPOINT_STORE_CONNECTION = "MODEL_MONITORING_ENDPOINT_STORE_CONNECTION"
168179
ACCESS_KEY = "MODEL_MONITORING_ACCESS_KEY"
169-
PIPELINES_ACCESS_KEY = "MODEL_MONITORING_PIPELINES_ACCESS_KEY"
170-
KAFKA_BROKERS = "KAFKA_BROKERS"
171180
STREAM_PATH = "STREAM_PATH"
172181
TSDB_CONNECTION = "TSDB_CONNECTION"
173182

183+
@classmethod
184+
def mandatory_secrets(cls):
185+
return [
186+
cls.ENDPOINT_STORE_CONNECTION,
187+
cls.STREAM_PATH,
188+
cls.TSDB_CONNECTION,
189+
]
190+
174191

175192
class ModelMonitoringStoreKinds:
176193
ENDPOINTS = "endpoints"
@@ -344,12 +361,6 @@ class ControllerPolicy:
344361
BASE_PERIOD = "base_period"
345362

346363

347-
class TSDBTarget:
348-
V3IO_TSDB = "v3io-tsdb"
349-
TDEngine = "tdengine"
350-
PROMETHEUS = "prometheus"
351-
352-
353364
class HistogramDataDriftApplicationConstants:
354365
NAME = "histogram-data-drift"
355366
GENERAL_RESULT_NAME = "general_drift"

mlrun/config.py

+4-11
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@
510510
"store_prefixes": {
511511
"default": "v3io:///users/pipelines/{project}/model-endpoints/{kind}",
512512
"user_space": "v3io:///projects/{project}/model-endpoints/{kind}",
513-
"stream": "",
513+
"stream": "", # TODO: Delete in 1.9.0
514514
"monitoring_application": "v3io:///users/pipelines/{project}/monitoring-apps/",
515515
},
516516
# Offline storage path can be either relative or a full path. This path is used for general offline data
@@ -523,11 +523,12 @@
523523
"parquet_batching_max_events": 10_000,
524524
"parquet_batching_timeout_secs": timedelta(minutes=1).total_seconds(),
525525
# See mlrun.model_monitoring.db.stores.ObjectStoreFactory for available options
526-
"store_type": "v3io-nosql",
526+
"store_type": "v3io-nosql", # TODO: Delete in 1.9.0
527527
"endpoint_store_connection": "",
528528
# See mlrun.model_monitoring.db.tsdb.ObjectTSDBFactory for available options
529-
"tsdb_connector_type": "v3io-tsdb",
530529
"tsdb_connection": "",
530+
# See mlrun.common.schemas.model_monitoring.constants.StreamKind for available options
531+
"stream_connection": "",
531532
},
532533
"secret_stores": {
533534
# Use only in testing scenarios (such as integration tests) to avoid using k8s for secrets (will use in-memory
@@ -1092,7 +1093,6 @@ def get_model_monitoring_file_target_path(
10921093
target: str = "online",
10931094
artifact_path: str = None,
10941095
function_name: str = None,
1095-
**kwargs,
10961096
) -> typing.Union[str, list[str]]:
10971097
"""Get the full path from the configuration based on the provided project and kind.
10981098
@@ -1114,13 +1114,6 @@ def get_model_monitoring_file_target_path(
11141114
"""
11151115

11161116
if target != "offline":
1117-
store_prefix_dict = (
1118-
mlrun.mlconf.model_endpoint_monitoring.store_prefixes.to_dict()
1119-
)
1120-
if store_prefix_dict.get(kind):
1121-
# Target exist in store prefix and has a valid string value
1122-
return store_prefix_dict[kind].format(project=project, **kwargs)
1123-
11241117
if (
11251118
function_name
11261119
and function_name

mlrun/db/base.py

+9
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ def enable_model_monitoring(
891891
image: str = "mlrun/mlrun",
892892
deploy_histogram_data_drift_app: bool = True,
893893
rebuild_images: bool = False,
894+
fetch_credentials_from_sys_config: bool = False,
894895
) -> None:
895896
pass
896897

@@ -917,3 +918,11 @@ def deploy_histogram_data_drift_app(
917918
self, project: str, image: str = "mlrun/mlrun"
918919
) -> None:
919920
pass
921+
922+
@abstractmethod
923+
def set_model_monitoring_credentials(
924+
self,
925+
project: str,
926+
credentials: dict[str, str],
927+
) -> None:
928+
pass

mlrun/db/httpdb.py

+33-8
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ def connect(self, secrets=None):
536536
server_cfg.get("model_monitoring_tsdb_connection")
537537
or config.model_endpoint_monitoring.tsdb_connection
538538
)
539+
config.model_endpoint_monitoring.stream_connection = (
540+
server_cfg.get("stream_connection")
541+
or config.model_endpoint_monitoring.stream_connection
542+
)
539543
config.packagers = server_cfg.get("packagers") or config.packagers
540544
server_data_prefixes = server_cfg.get("feature_store_data_prefixes") or {}
541545
for prefix in ["default", "nosql", "redisnosql"]:
@@ -3397,6 +3401,7 @@ def enable_model_monitoring(
33973401
image: str = "mlrun/mlrun",
33983402
deploy_histogram_data_drift_app: bool = True,
33993403
rebuild_images: bool = False,
3404+
fetch_credentials_from_sys_config: bool = False,
34003405
) -> None:
34013406
"""
34023407
Deploy model monitoring application controller, writer and stream functions.
@@ -3406,14 +3411,16 @@ def enable_model_monitoring(
34063411
The stream function goal is to monitor the log of the data stream. It is triggered when a new log entry
34073412
is detected. It processes the new events into statistics that are then written to statistics databases.
34083413
3409-
:param project: Project name.
3410-
:param base_period: The time period in minutes in which the model monitoring controller
3411-
function triggers. By default, the base period is 10 minutes.
3412-
:param image: The image of the model monitoring controller, writer & monitoring
3413-
stream functions, which are real time nuclio functions.
3414-
By default, the image is mlrun/mlrun.
3415-
:param deploy_histogram_data_drift_app: If true, deploy the default histogram-based data drift application.
3416-
:param rebuild_images: If true, force rebuild of model monitoring infrastructure images.
3414+
:param project: Project name.
3415+
:param base_period: The time period in minutes in which the model monitoring controller
3416+
function triggers. By default, the base period is 10 minutes.
3417+
:param image: The image of the model monitoring controller, writer & monitoring
3418+
stream functions, which are real time nuclio functions.
3419+
By default, the image is mlrun/mlrun.
3420+
:param deploy_histogram_data_drift_app: If true, deploy the default histogram-based data drift application.
3421+
:param rebuild_images: If true, force rebuild of model monitoring infrastructure images.
3422+
:param fetch_credentials_from_sys_config: If true, fetch the credentials from the system configuration.
3423+
34173424
"""
34183425
self.api_call(
34193426
method=mlrun.common.types.HTTPMethod.POST,
@@ -3423,6 +3430,7 @@ def enable_model_monitoring(
34233430
"image": image,
34243431
"deploy_histogram_data_drift_app": deploy_histogram_data_drift_app,
34253432
"rebuild_images": rebuild_images,
3433+
"fetch_credentials_from_sys_config": fetch_credentials_from_sys_config,
34263434
},
34273435
)
34283436

@@ -3548,6 +3556,23 @@ def deploy_histogram_data_drift_app(
35483556
params={"image": image},
35493557
)
35503558

3559+
def set_model_monitoring_credentials(
3560+
self,
3561+
project: str,
3562+
credentials: dict[str, str],
3563+
) -> None:
3564+
"""
3565+
Set the credentials for the model monitoring application.
3566+
3567+
:param project: Project name.
3568+
:param credentials: Credentials to set.
3569+
"""
3570+
self.api_call(
3571+
method=mlrun.common.types.HTTPMethod.POST,
3572+
path=f"projects/{project}/model-monitoring/set-model-monitoring-credentials",
3573+
params={**credentials},
3574+
)
3575+
35513576
def create_hub_source(
35523577
self, source: Union[dict, mlrun.common.schemas.IndexedHubSource]
35533578
):

mlrun/db/nopdb.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ def enable_model_monitoring(
708708
image: str = "mlrun/mlrun",
709709
deploy_histogram_data_drift_app: bool = True,
710710
rebuild_images: bool = False,
711+
fetch_credentials_from_sys_config: bool = False,
711712
) -> None:
712713
pass
713714

@@ -730,7 +731,14 @@ def delete_model_monitoring_function(
730731
def deploy_histogram_data_drift_app(
731732
self, project: str, image: str = "mlrun/mlrun"
732733
) -> None:
733-
raise NotImplementedError
734+
pass
735+
736+
def set_model_monitoring_credentials(
737+
self,
738+
project: str,
739+
credentials: dict[str, str],
740+
) -> None:
741+
pass
734742

735743
def generate_event(
736744
self, name: str, event_data: Union[dict, mlrun.common.schemas.Event], project=""

mlrun/model_monitoring/db/stores/__init__.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,12 @@ def get_store_object(
111111
):
112112
store_type = mlrun.common.schemas.model_monitoring.ModelEndpointTarget.SQL
113113
kwargs["store_connection_string"] = store_connection_string
114+
elif store_connection_string and store_connection_string == "v3io":
115+
store_type = (
116+
mlrun.common.schemas.model_monitoring.ModelEndpointTarget.V3IO_NOSQL
117+
)
114118
else:
115-
# Set the default store type if no connection has been set
116-
store_type = mlrun.mlconf.model_endpoint_monitoring.store_type
117-
119+
store_type = None
118120
# Get store type value from ObjectStoreFactory enum class
119121
store_type_fact = ObjectStoreFactory(store_type)
120122

mlrun/model_monitoring/db/tsdb/__init__.py

+4-7
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ def _missing_(cls, value: typing.Any):
6464

6565
def get_tsdb_connector(
6666
project: str,
67-
tsdb_connector_type: str = "",
6867
secret_provider: typing.Optional[typing.Callable[[str], str]] = None,
6968
**kwargs,
7069
) -> TSDBConnector:
@@ -86,12 +85,10 @@ def get_tsdb_connector(
8685
if tsdb_connection_string and tsdb_connection_string.startswith("taosws"):
8786
tsdb_connector_type = mlrun.common.schemas.model_monitoring.TSDBTarget.TDEngine
8887
kwargs["connection_string"] = tsdb_connection_string
89-
90-
# Set the default TSDB connector type if no connection has been set
91-
tsdb_connector_type = (
92-
tsdb_connector_type
93-
or mlrun.mlconf.model_endpoint_monitoring.tsdb_connector_type
94-
)
88+
elif tsdb_connection_string and tsdb_connection_string == "v3io":
89+
tsdb_connector_type = mlrun.common.schemas.model_monitoring.TSDBTarget.V3IO_TSDB
90+
else:
91+
tsdb_connector_type = None
9592

9693
# Get connector type value from ObjectTSDBFactory enum class
9794
tsdb_connector_factory = ObjectTSDBFactory(tsdb_connector_type)

mlrun/model_monitoring/helpers.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,17 @@ def get_stream_path(
5959

6060
stream_uri = mlrun.get_secret_or_env(
6161
mlrun.common.schemas.model_monitoring.ProjectSecretKeys.STREAM_PATH
62-
) or mlrun.mlconf.get_model_monitoring_file_target_path(
63-
project=project,
64-
kind=mlrun.common.schemas.model_monitoring.FileTargetKind.STREAM,
65-
target="online",
66-
function_name=function_name,
6762
)
6863

64+
if not stream_uri or stream_uri == "v3io":
65+
# TODO : remove the first part of this condition in 1.9.0
66+
stream_uri = mlrun.mlconf.get_model_monitoring_file_target_path(
67+
project=project,
68+
kind=mlrun.common.schemas.model_monitoring.FileTargetKind.STREAM,
69+
target="online",
70+
function_name=function_name,
71+
)
72+
6973
if isinstance(stream_uri, list): # ML-6043 - user side gets only the new stream uri
7074
stream_uri = stream_uri[1] # get new stream path, under projects
7175
return mlrun.common.model_monitoring.helpers.parse_monitoring_stream_path(

0 commit comments

Comments
 (0)