mlrun 1.3.3rc1__py3-none-any.whl → 1.4.0__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 +3 -3
- mlrun/__main__.py +79 -37
- mlrun/api/__init__.py +1 -1
- mlrun/api/api/__init__.py +1 -1
- mlrun/api/api/api.py +4 -4
- mlrun/api/api/deps.py +10 -21
- mlrun/api/api/endpoints/__init__.py +1 -1
- mlrun/api/api/endpoints/artifacts.py +64 -36
- mlrun/api/api/endpoints/auth.py +4 -4
- mlrun/api/api/endpoints/background_tasks.py +11 -11
- mlrun/api/api/endpoints/client_spec.py +5 -5
- mlrun/api/api/endpoints/clusterization_spec.py +6 -4
- mlrun/api/api/endpoints/feature_store.py +124 -115
- mlrun/api/api/endpoints/files.py +22 -14
- mlrun/api/api/endpoints/frontend_spec.py +28 -21
- mlrun/api/api/endpoints/functions.py +142 -87
- mlrun/api/api/endpoints/grafana_proxy.py +89 -442
- mlrun/api/api/endpoints/healthz.py +20 -7
- mlrun/api/api/endpoints/hub.py +320 -0
- mlrun/api/api/endpoints/internal/__init__.py +1 -1
- mlrun/api/api/endpoints/internal/config.py +1 -1
- mlrun/api/api/endpoints/internal/memory_reports.py +9 -9
- mlrun/api/api/endpoints/logs.py +11 -11
- mlrun/api/api/endpoints/model_endpoints.py +74 -70
- mlrun/api/api/endpoints/operations.py +13 -9
- mlrun/api/api/endpoints/pipelines.py +93 -88
- mlrun/api/api/endpoints/projects.py +35 -35
- mlrun/api/api/endpoints/runs.py +69 -27
- mlrun/api/api/endpoints/runtime_resources.py +28 -28
- mlrun/api/api/endpoints/schedules.py +98 -41
- mlrun/api/api/endpoints/secrets.py +37 -32
- mlrun/api/api/endpoints/submit.py +12 -12
- mlrun/api/api/endpoints/tags.py +20 -22
- mlrun/api/api/utils.py +251 -42
- mlrun/api/constants.py +1 -1
- mlrun/api/crud/__init__.py +18 -15
- mlrun/api/crud/artifacts.py +10 -10
- mlrun/api/crud/client_spec.py +4 -4
- mlrun/api/crud/clusterization_spec.py +3 -3
- mlrun/api/crud/feature_store.py +54 -46
- mlrun/api/crud/functions.py +3 -3
- mlrun/api/crud/hub.py +312 -0
- mlrun/api/crud/logs.py +11 -9
- mlrun/api/crud/model_monitoring/__init__.py +3 -3
- mlrun/api/crud/model_monitoring/grafana.py +435 -0
- mlrun/api/crud/model_monitoring/model_endpoints.py +352 -129
- mlrun/api/crud/notifications.py +149 -0
- mlrun/api/crud/pipelines.py +67 -52
- mlrun/api/crud/projects.py +51 -23
- mlrun/api/crud/runs.py +7 -5
- mlrun/api/crud/runtime_resources.py +13 -13
- mlrun/api/{db/filedb → crud/runtimes}/__init__.py +1 -1
- mlrun/api/crud/runtimes/nuclio/__init__.py +14 -0
- mlrun/api/crud/runtimes/nuclio/function.py +505 -0
- mlrun/api/crud/runtimes/nuclio/helpers.py +310 -0
- mlrun/api/crud/secrets.py +88 -46
- mlrun/api/crud/tags.py +5 -5
- mlrun/api/db/__init__.py +1 -1
- mlrun/api/db/base.py +102 -54
- mlrun/api/db/init_db.py +2 -3
- mlrun/api/db/session.py +4 -12
- mlrun/api/db/sqldb/__init__.py +1 -1
- mlrun/api/db/sqldb/db.py +439 -196
- mlrun/api/db/sqldb/helpers.py +1 -1
- mlrun/api/db/sqldb/models/__init__.py +3 -3
- mlrun/api/db/sqldb/models/models_mysql.py +82 -64
- mlrun/api/db/sqldb/models/models_sqlite.py +76 -64
- mlrun/api/db/sqldb/session.py +27 -20
- mlrun/api/initial_data.py +82 -24
- mlrun/api/launcher.py +196 -0
- mlrun/api/main.py +91 -22
- mlrun/api/middlewares.py +6 -5
- mlrun/api/migrations_mysql/env.py +1 -1
- mlrun/api/migrations_mysql/versions/28383af526f3_market_place_to_hub.py +40 -0
- mlrun/api/migrations_mysql/versions/32bae1b0e29c_increase_timestamp_fields_precision.py +1 -1
- mlrun/api/migrations_mysql/versions/4903aef6a91d_tag_foreign_key_and_cascades.py +1 -1
- mlrun/api/migrations_mysql/versions/5f1351c88a19_adding_background_tasks_table.py +1 -1
- mlrun/api/migrations_mysql/versions/88e656800d6a_add_requested_logs_column_and_index_to_.py +1 -1
- mlrun/api/migrations_mysql/versions/9d16de5f03a7_adding_data_versions_table.py +1 -1
- mlrun/api/migrations_mysql/versions/b86f5b53f3d7_adding_name_and_updated_to_runs_table.py +1 -1
- mlrun/api/migrations_mysql/versions/c4af40b0bf61_init.py +1 -1
- mlrun/api/migrations_mysql/versions/c905d15bd91d_notifications.py +72 -0
- mlrun/api/migrations_mysql/versions/ee041e8fdaa0_adding_next_run_time_column_to_schedule_.py +1 -1
- mlrun/api/migrations_sqlite/env.py +1 -1
- mlrun/api/migrations_sqlite/versions/11f8dd2dc9fe_init.py +1 -1
- mlrun/api/migrations_sqlite/versions/1c954f8cb32d_schedule_last_run_uri.py +1 -1
- mlrun/api/migrations_sqlite/versions/2b6d23c715aa_adding_feature_sets.py +1 -1
- mlrun/api/migrations_sqlite/versions/4acd9430b093_market_place_to_hub.py +77 -0
- mlrun/api/migrations_sqlite/versions/6401142f2d7c_adding_next_run_time_column_to_schedule_.py +1 -1
- mlrun/api/migrations_sqlite/versions/64d90a1a69bc_adding_background_tasks_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/803438ecd005_add_requested_logs_column_to_runs.py +1 -1
- mlrun/api/migrations_sqlite/versions/863114f0c659_refactoring_feature_set.py +1 -1
- mlrun/api/migrations_sqlite/versions/959ae00528ad_notifications.py +63 -0
- mlrun/api/migrations_sqlite/versions/accf9fc83d38_adding_data_versions_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/b68e8e897a28_schedule_labels.py +1 -1
- mlrun/api/migrations_sqlite/versions/bcd0c1f9720c_adding_project_labels.py +1 -1
- mlrun/api/migrations_sqlite/versions/cf21882f938e_schedule_id.py +1 -1
- mlrun/api/migrations_sqlite/versions/d781f58f607f_tag_object_name_string.py +1 -1
- mlrun/api/migrations_sqlite/versions/deac06871ace_adding_marketplace_sources_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/e1dd5983c06b_schedule_concurrency_limit.py +1 -1
- mlrun/api/migrations_sqlite/versions/e5594ed3ab53_adding_name_and_updated_to_runs_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/f4249b4ba6fa_adding_feature_vectors.py +1 -1
- mlrun/api/migrations_sqlite/versions/f7b5a1a03629_adding_feature_labels.py +1 -1
- mlrun/api/schemas/__init__.py +216 -138
- mlrun/api/utils/__init__.py +1 -1
- mlrun/api/utils/asyncio.py +1 -1
- mlrun/api/utils/auth/__init__.py +1 -1
- mlrun/api/utils/auth/providers/__init__.py +1 -1
- mlrun/api/utils/auth/providers/base.py +7 -7
- mlrun/api/utils/auth/providers/nop.py +6 -7
- mlrun/api/utils/auth/providers/opa.py +17 -17
- mlrun/api/utils/auth/verifier.py +36 -34
- mlrun/api/utils/background_tasks.py +24 -24
- mlrun/{builder.py → api/utils/builder.py} +216 -123
- mlrun/api/utils/clients/__init__.py +1 -1
- mlrun/api/utils/clients/chief.py +19 -4
- mlrun/api/utils/clients/iguazio.py +106 -60
- mlrun/api/utils/clients/log_collector.py +1 -1
- mlrun/api/utils/clients/nuclio.py +23 -23
- mlrun/api/utils/clients/protocols/grpc.py +2 -2
- mlrun/api/utils/db/__init__.py +1 -1
- mlrun/api/utils/db/alembic.py +1 -1
- mlrun/api/utils/db/backup.py +1 -1
- mlrun/api/utils/db/mysql.py +24 -25
- mlrun/api/utils/db/sql_collation.py +1 -1
- mlrun/api/utils/db/sqlite_migration.py +2 -2
- mlrun/api/utils/events/__init__.py +14 -0
- mlrun/api/utils/events/base.py +57 -0
- mlrun/api/utils/events/events_factory.py +41 -0
- mlrun/api/utils/events/iguazio.py +217 -0
- mlrun/api/utils/events/nop.py +55 -0
- mlrun/api/utils/helpers.py +16 -13
- mlrun/api/utils/memory_reports.py +1 -1
- mlrun/api/utils/periodic.py +6 -3
- mlrun/api/utils/projects/__init__.py +1 -1
- mlrun/api/utils/projects/follower.py +33 -33
- mlrun/api/utils/projects/leader.py +36 -34
- mlrun/api/utils/projects/member.py +27 -27
- mlrun/api/utils/projects/remotes/__init__.py +1 -1
- mlrun/api/utils/projects/remotes/follower.py +13 -13
- mlrun/api/utils/projects/remotes/leader.py +10 -10
- mlrun/api/utils/projects/remotes/nop_follower.py +27 -21
- mlrun/api/utils/projects/remotes/nop_leader.py +17 -16
- mlrun/api/utils/scheduler.py +140 -51
- mlrun/api/utils/singletons/__init__.py +1 -1
- mlrun/api/utils/singletons/db.py +9 -15
- mlrun/api/utils/singletons/k8s.py +677 -5
- mlrun/api/utils/singletons/logs_dir.py +1 -1
- mlrun/api/utils/singletons/project_member.py +1 -1
- mlrun/api/utils/singletons/scheduler.py +1 -1
- mlrun/artifacts/__init__.py +2 -2
- mlrun/artifacts/base.py +8 -2
- mlrun/artifacts/dataset.py +5 -3
- mlrun/artifacts/manager.py +7 -1
- mlrun/artifacts/model.py +15 -4
- mlrun/artifacts/plots.py +1 -1
- mlrun/common/__init__.py +1 -1
- mlrun/common/constants.py +15 -0
- mlrun/common/model_monitoring.py +209 -0
- mlrun/common/schemas/__init__.py +167 -0
- mlrun/{api → common}/schemas/artifact.py +13 -14
- mlrun/{api → common}/schemas/auth.py +10 -8
- mlrun/{api → common}/schemas/background_task.py +3 -3
- mlrun/{api → common}/schemas/client_spec.py +1 -1
- mlrun/{api → common}/schemas/clusterization_spec.py +3 -3
- mlrun/{api → common}/schemas/constants.py +21 -8
- mlrun/common/schemas/events.py +36 -0
- mlrun/{api → common}/schemas/feature_store.py +2 -1
- mlrun/{api → common}/schemas/frontend_spec.py +7 -6
- mlrun/{api → common}/schemas/function.py +5 -5
- mlrun/{api → common}/schemas/http.py +3 -3
- mlrun/common/schemas/hub.py +134 -0
- mlrun/{api → common}/schemas/k8s.py +3 -3
- mlrun/{api → common}/schemas/memory_reports.py +1 -1
- mlrun/common/schemas/model_endpoints.py +342 -0
- mlrun/common/schemas/notification.py +57 -0
- mlrun/{api → common}/schemas/object.py +6 -6
- mlrun/{api → common}/schemas/pipeline.py +3 -3
- mlrun/{api → common}/schemas/project.py +6 -5
- mlrun/common/schemas/regex.py +24 -0
- mlrun/common/schemas/runs.py +30 -0
- mlrun/{api → common}/schemas/runtime_resource.py +3 -3
- mlrun/{api → common}/schemas/schedule.py +19 -7
- mlrun/{api → common}/schemas/secret.py +3 -3
- mlrun/{api → common}/schemas/tag.py +2 -2
- mlrun/common/types.py +25 -0
- mlrun/config.py +152 -20
- mlrun/data_types/__init__.py +7 -2
- mlrun/data_types/data_types.py +4 -2
- mlrun/data_types/infer.py +1 -1
- mlrun/data_types/spark.py +10 -3
- mlrun/datastore/__init__.py +10 -3
- mlrun/datastore/azure_blob.py +1 -1
- mlrun/datastore/base.py +185 -53
- mlrun/datastore/datastore.py +1 -1
- mlrun/datastore/filestore.py +1 -1
- mlrun/datastore/google_cloud_storage.py +1 -1
- mlrun/datastore/inmem.py +4 -1
- mlrun/datastore/redis.py +1 -1
- mlrun/datastore/s3.py +1 -1
- mlrun/datastore/sources.py +192 -70
- mlrun/datastore/spark_udf.py +44 -0
- mlrun/datastore/store_resources.py +4 -4
- mlrun/datastore/targets.py +115 -45
- mlrun/datastore/utils.py +127 -5
- mlrun/datastore/v3io.py +1 -1
- mlrun/datastore/wasbfs/__init__.py +1 -1
- mlrun/datastore/wasbfs/fs.py +1 -1
- mlrun/db/__init__.py +7 -5
- mlrun/db/base.py +112 -68
- mlrun/db/httpdb.py +445 -277
- mlrun/db/nopdb.py +491 -0
- mlrun/db/sqldb.py +112 -65
- mlrun/errors.py +6 -1
- mlrun/execution.py +44 -22
- mlrun/feature_store/__init__.py +1 -1
- mlrun/feature_store/api.py +143 -95
- mlrun/feature_store/common.py +16 -20
- mlrun/feature_store/feature_set.py +42 -12
- mlrun/feature_store/feature_vector.py +32 -21
- mlrun/feature_store/ingestion.py +9 -12
- mlrun/feature_store/retrieval/__init__.py +3 -2
- mlrun/feature_store/retrieval/base.py +388 -66
- mlrun/feature_store/retrieval/dask_merger.py +63 -151
- mlrun/feature_store/retrieval/job.py +30 -12
- mlrun/feature_store/retrieval/local_merger.py +40 -133
- mlrun/feature_store/retrieval/spark_merger.py +129 -127
- mlrun/feature_store/retrieval/storey_merger.py +173 -0
- mlrun/feature_store/steps.py +132 -15
- mlrun/features.py +8 -3
- mlrun/frameworks/__init__.py +1 -1
- mlrun/frameworks/_common/__init__.py +1 -1
- mlrun/frameworks/_common/artifacts_library.py +1 -1
- mlrun/frameworks/_common/mlrun_interface.py +1 -1
- mlrun/frameworks/_common/model_handler.py +1 -1
- mlrun/frameworks/_common/plan.py +1 -1
- mlrun/frameworks/_common/producer.py +1 -1
- mlrun/frameworks/_common/utils.py +1 -1
- mlrun/frameworks/_dl_common/__init__.py +1 -1
- mlrun/frameworks/_dl_common/loggers/__init__.py +1 -1
- mlrun/frameworks/_dl_common/loggers/logger.py +1 -1
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +1 -1
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +1 -1
- mlrun/frameworks/_dl_common/model_handler.py +1 -1
- mlrun/frameworks/_dl_common/utils.py +1 -1
- mlrun/frameworks/_ml_common/__init__.py +1 -1
- mlrun/frameworks/_ml_common/artifacts_library.py +1 -1
- mlrun/frameworks/_ml_common/loggers/__init__.py +1 -1
- mlrun/frameworks/_ml_common/loggers/logger.py +1 -1
- mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +1 -1
- mlrun/frameworks/_ml_common/model_handler.py +1 -1
- mlrun/frameworks/_ml_common/pkl_model_server.py +13 -1
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/__init__.py +1 -1
- mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +1 -6
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +1 -1
- mlrun/frameworks/_ml_common/producer.py +1 -1
- mlrun/frameworks/_ml_common/utils.py +1 -1
- mlrun/frameworks/auto_mlrun/__init__.py +1 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +1 -1
- mlrun/frameworks/huggingface/__init__.py +1 -1
- mlrun/frameworks/huggingface/model_server.py +1 -1
- mlrun/frameworks/lgbm/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/callback.py +1 -1
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/model_mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/model_handler.py +1 -1
- mlrun/frameworks/lgbm/model_server.py +1 -1
- mlrun/frameworks/lgbm/utils.py +1 -1
- mlrun/frameworks/onnx/__init__.py +1 -1
- mlrun/frameworks/onnx/dataset.py +1 -1
- mlrun/frameworks/onnx/mlrun_interface.py +1 -1
- mlrun/frameworks/onnx/model_handler.py +1 -1
- mlrun/frameworks/onnx/model_server.py +1 -1
- mlrun/frameworks/parallel_coordinates.py +1 -1
- mlrun/frameworks/pytorch/__init__.py +1 -1
- mlrun/frameworks/pytorch/callbacks/__init__.py +1 -1
- mlrun/frameworks/pytorch/callbacks/callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks_handler.py +1 -1
- mlrun/frameworks/pytorch/mlrun_interface.py +1 -1
- mlrun/frameworks/pytorch/model_handler.py +1 -1
- mlrun/frameworks/pytorch/model_server.py +1 -1
- mlrun/frameworks/pytorch/utils.py +1 -1
- mlrun/frameworks/sklearn/__init__.py +1 -1
- mlrun/frameworks/sklearn/estimator.py +1 -1
- mlrun/frameworks/sklearn/metric.py +1 -1
- mlrun/frameworks/sklearn/metrics_library.py +1 -1
- mlrun/frameworks/sklearn/mlrun_interface.py +1 -1
- mlrun/frameworks/sklearn/model_handler.py +1 -1
- mlrun/frameworks/sklearn/utils.py +1 -1
- mlrun/frameworks/tf_keras/__init__.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/mlrun_interface.py +1 -1
- mlrun/frameworks/tf_keras/model_handler.py +1 -1
- mlrun/frameworks/tf_keras/model_server.py +1 -1
- mlrun/frameworks/tf_keras/utils.py +1 -1
- mlrun/frameworks/xgboost/__init__.py +1 -1
- mlrun/frameworks/xgboost/mlrun_interface.py +1 -1
- mlrun/frameworks/xgboost/model_handler.py +1 -1
- mlrun/frameworks/xgboost/utils.py +1 -1
- mlrun/k8s_utils.py +14 -765
- mlrun/kfpops.py +14 -17
- mlrun/launcher/__init__.py +13 -0
- mlrun/launcher/base.py +406 -0
- mlrun/launcher/client.py +159 -0
- mlrun/launcher/factory.py +50 -0
- mlrun/launcher/local.py +276 -0
- mlrun/launcher/remote.py +178 -0
- mlrun/lists.py +10 -2
- mlrun/mlutils/__init__.py +1 -1
- mlrun/mlutils/data.py +1 -1
- mlrun/mlutils/models.py +1 -1
- mlrun/mlutils/plots.py +1 -1
- mlrun/model.py +252 -14
- mlrun/model_monitoring/__init__.py +41 -0
- mlrun/model_monitoring/features_drift_table.py +1 -1
- mlrun/model_monitoring/helpers.py +123 -38
- mlrun/model_monitoring/model_endpoint.py +144 -0
- mlrun/model_monitoring/model_monitoring_batch.py +310 -259
- mlrun/model_monitoring/stores/__init__.py +106 -0
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +448 -0
- mlrun/model_monitoring/stores/model_endpoint_store.py +147 -0
- mlrun/model_monitoring/stores/models/__init__.py +23 -0
- mlrun/model_monitoring/stores/models/base.py +18 -0
- mlrun/model_monitoring/stores/models/mysql.py +100 -0
- mlrun/model_monitoring/stores/models/sqlite.py +98 -0
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +370 -0
- mlrun/model_monitoring/stream_processing_fs.py +239 -271
- mlrun/package/__init__.py +163 -0
- mlrun/package/context_handler.py +325 -0
- mlrun/package/errors.py +47 -0
- mlrun/package/packager.py +298 -0
- mlrun/{runtimes/package → package/packagers}/__init__.py +3 -1
- mlrun/package/packagers/default_packager.py +422 -0
- mlrun/package/packagers/numpy_packagers.py +612 -0
- mlrun/package/packagers/pandas_packagers.py +968 -0
- mlrun/package/packagers/python_standard_library_packagers.py +616 -0
- mlrun/package/packagers_manager.py +786 -0
- mlrun/package/utils/__init__.py +53 -0
- mlrun/package/utils/_archiver.py +226 -0
- mlrun/package/utils/_formatter.py +211 -0
- mlrun/package/utils/_pickler.py +234 -0
- mlrun/package/utils/_supported_format.py +71 -0
- mlrun/package/utils/log_hint_utils.py +93 -0
- mlrun/package/utils/type_hint_utils.py +298 -0
- mlrun/platforms/__init__.py +1 -1
- mlrun/platforms/iguazio.py +34 -2
- mlrun/platforms/other.py +1 -1
- mlrun/projects/__init__.py +1 -1
- mlrun/projects/operations.py +14 -9
- mlrun/projects/pipelines.py +31 -13
- mlrun/projects/project.py +762 -238
- mlrun/render.py +49 -19
- mlrun/run.py +57 -326
- mlrun/runtimes/__init__.py +3 -9
- mlrun/runtimes/base.py +247 -784
- mlrun/runtimes/constants.py +1 -1
- mlrun/runtimes/daskjob.py +45 -41
- mlrun/runtimes/funcdoc.py +43 -7
- mlrun/runtimes/function.py +66 -656
- mlrun/runtimes/function_reference.py +1 -1
- mlrun/runtimes/generators.py +1 -1
- mlrun/runtimes/kubejob.py +99 -116
- mlrun/runtimes/local.py +59 -66
- mlrun/runtimes/mpijob/__init__.py +1 -1
- mlrun/runtimes/mpijob/abstract.py +13 -15
- mlrun/runtimes/mpijob/v1.py +3 -1
- mlrun/runtimes/mpijob/v1alpha1.py +1 -1
- mlrun/runtimes/nuclio.py +1 -1
- mlrun/runtimes/pod.py +51 -26
- mlrun/runtimes/remotesparkjob.py +3 -1
- mlrun/runtimes/serving.py +12 -4
- mlrun/runtimes/sparkjob/__init__.py +1 -2
- mlrun/runtimes/sparkjob/abstract.py +44 -31
- mlrun/runtimes/sparkjob/spark3job.py +11 -9
- mlrun/runtimes/utils.py +61 -42
- mlrun/secrets.py +16 -18
- mlrun/serving/__init__.py +3 -2
- mlrun/serving/merger.py +1 -1
- mlrun/serving/remote.py +1 -1
- mlrun/serving/routers.py +39 -42
- mlrun/serving/server.py +23 -13
- mlrun/serving/serving_wrapper.py +1 -1
- mlrun/serving/states.py +172 -39
- mlrun/serving/utils.py +1 -1
- mlrun/serving/v1_serving.py +1 -1
- mlrun/serving/v2_serving.py +29 -21
- mlrun/utils/__init__.py +1 -2
- mlrun/utils/async_http.py +8 -1
- mlrun/utils/azure_vault.py +1 -1
- mlrun/utils/clones.py +2 -2
- mlrun/utils/condition_evaluator.py +65 -0
- mlrun/utils/db.py +52 -0
- mlrun/utils/helpers.py +188 -13
- mlrun/utils/http.py +89 -54
- mlrun/utils/logger.py +48 -8
- mlrun/utils/model_monitoring.py +132 -100
- mlrun/utils/notifications/__init__.py +1 -1
- mlrun/utils/notifications/notification/__init__.py +8 -6
- mlrun/utils/notifications/notification/base.py +20 -14
- mlrun/utils/notifications/notification/console.py +7 -4
- mlrun/utils/notifications/notification/git.py +36 -19
- mlrun/utils/notifications/notification/ipython.py +10 -8
- mlrun/utils/notifications/notification/slack.py +18 -13
- mlrun/utils/notifications/notification_pusher.py +377 -56
- mlrun/utils/regex.py +6 -1
- mlrun/utils/singleton.py +1 -1
- mlrun/utils/v3io_clients.py +1 -1
- mlrun/utils/vault.py +270 -269
- mlrun/utils/version/__init__.py +1 -1
- mlrun/utils/version/version.json +2 -2
- mlrun/utils/version/version.py +1 -1
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/METADATA +16 -10
- mlrun-1.4.0.dist-info/RECORD +434 -0
- mlrun/api/api/endpoints/marketplace.py +0 -257
- mlrun/api/crud/marketplace.py +0 -221
- mlrun/api/crud/model_monitoring/model_endpoint_store.py +0 -847
- mlrun/api/db/filedb/db.py +0 -518
- mlrun/api/schemas/marketplace.py +0 -128
- mlrun/api/schemas/model_endpoints.py +0 -185
- mlrun/db/filedb.py +0 -891
- mlrun/feature_store/retrieval/online.py +0 -92
- mlrun/model_monitoring/constants.py +0 -67
- mlrun/runtimes/package/context_handler.py +0 -711
- mlrun/runtimes/sparkjob/spark2job.py +0 -59
- mlrun-1.3.3rc1.dist-info/RECORD +0 -381
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/LICENSE +0 -0
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/WHEEL +0 -0
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/entry_points.txt +0 -0
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/top_level.txt +0 -0
mlrun/utils/model_monitoring.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -13,97 +13,16 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
#
|
|
15
15
|
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
from
|
|
19
|
-
from typing import Optional, Union
|
|
16
|
+
import json
|
|
17
|
+
import warnings
|
|
18
|
+
from typing import Union
|
|
20
19
|
|
|
21
20
|
import mlrun
|
|
21
|
+
import mlrun.common.model_monitoring as model_monitoring_constants
|
|
22
22
|
import mlrun.model
|
|
23
|
-
import mlrun.model_monitoring.constants as model_monitoring_constants
|
|
24
23
|
import mlrun.platforms.iguazio
|
|
25
|
-
|
|
26
|
-
from mlrun.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@dataclass
|
|
30
|
-
class FunctionURI:
|
|
31
|
-
project: str
|
|
32
|
-
function: str
|
|
33
|
-
tag: Optional[str] = None
|
|
34
|
-
hash_key: Optional[str] = None
|
|
35
|
-
|
|
36
|
-
@classmethod
|
|
37
|
-
def from_string(cls, function_uri):
|
|
38
|
-
project, uri, tag, hash_key = mlrun.utils.parse_versioned_object_uri(
|
|
39
|
-
function_uri
|
|
40
|
-
)
|
|
41
|
-
return cls(
|
|
42
|
-
project=project,
|
|
43
|
-
function=uri,
|
|
44
|
-
tag=tag or None,
|
|
45
|
-
hash_key=hash_key or None,
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@dataclass
|
|
50
|
-
class VersionedModel:
|
|
51
|
-
model: str
|
|
52
|
-
version: Optional[str]
|
|
53
|
-
|
|
54
|
-
@classmethod
|
|
55
|
-
def from_string(cls, model):
|
|
56
|
-
try:
|
|
57
|
-
model, version = model.split(":")
|
|
58
|
-
except ValueError:
|
|
59
|
-
model, version = model, None
|
|
60
|
-
|
|
61
|
-
return cls(model, version)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@dataclass
|
|
65
|
-
class EndpointUID:
|
|
66
|
-
project: str
|
|
67
|
-
function: str
|
|
68
|
-
function_tag: str
|
|
69
|
-
function_hash_key: str
|
|
70
|
-
model: str
|
|
71
|
-
model_version: str
|
|
72
|
-
uid: Optional[str] = None
|
|
73
|
-
|
|
74
|
-
def __post_init__(self):
|
|
75
|
-
function_ref = (
|
|
76
|
-
f"{self.function}_{self.function_tag or self.function_hash_key or 'N/A'}"
|
|
77
|
-
)
|
|
78
|
-
versioned_model = f"{self.model}_{self.model_version or 'N/A'}"
|
|
79
|
-
unique_string = f"{self.project}_{function_ref}_{versioned_model}"
|
|
80
|
-
self.uid = hashlib.sha1(unique_string.encode("utf-8")).hexdigest()
|
|
81
|
-
|
|
82
|
-
def __str__(self):
|
|
83
|
-
return self.uid
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def create_model_endpoint_id(function_uri: str, versioned_model: str):
|
|
87
|
-
function_uri = FunctionURI.from_string(function_uri)
|
|
88
|
-
versioned_model = VersionedModel.from_string(versioned_model)
|
|
89
|
-
|
|
90
|
-
if (
|
|
91
|
-
not function_uri.project
|
|
92
|
-
or not function_uri.function
|
|
93
|
-
or not versioned_model.model
|
|
94
|
-
):
|
|
95
|
-
raise ValueError("Both function_uri and versioned_model have to be initialized")
|
|
96
|
-
|
|
97
|
-
uid = EndpointUID(
|
|
98
|
-
function_uri.project,
|
|
99
|
-
function_uri.function,
|
|
100
|
-
function_uri.tag,
|
|
101
|
-
function_uri.hash_key,
|
|
102
|
-
versioned_model.model,
|
|
103
|
-
versioned_model.version,
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
return uid
|
|
24
|
+
from mlrun.common.schemas.schedule import ScheduleCronTrigger
|
|
25
|
+
from mlrun.config import is_running_as_api
|
|
107
26
|
|
|
108
27
|
|
|
109
28
|
def parse_model_endpoint_project_prefix(path: str, project_name: str):
|
|
@@ -116,29 +35,20 @@ def parse_model_endpoint_store_prefix(store_prefix: str):
|
|
|
116
35
|
return endpoint, container, path
|
|
117
36
|
|
|
118
37
|
|
|
119
|
-
def set_project_model_monitoring_credentials(
|
|
120
|
-
access_key: str, project: Optional[str] = None
|
|
121
|
-
):
|
|
38
|
+
def set_project_model_monitoring_credentials(access_key: str, project: str = None):
|
|
122
39
|
"""Set the credentials that will be used by the project's model monitoring
|
|
123
40
|
infrastructure functions.
|
|
124
41
|
The supplied credentials must have data access
|
|
125
|
-
|
|
126
42
|
:param access_key: Model Monitoring access key for managing user permissions.
|
|
127
43
|
:param project: The name of the model monitoring project.
|
|
128
44
|
"""
|
|
129
45
|
mlrun.get_run_db().create_project_secrets(
|
|
130
46
|
project=project or mlrun.mlconf.default_project,
|
|
131
|
-
provider=mlrun.
|
|
132
|
-
secrets={
|
|
47
|
+
provider=mlrun.common.schemas.SecretProviderName.kubernetes,
|
|
48
|
+
secrets={model_monitoring_constants.ProjectSecretKeys.ACCESS_KEY: access_key},
|
|
133
49
|
)
|
|
134
50
|
|
|
135
51
|
|
|
136
|
-
class EndpointType(enum.IntEnum):
|
|
137
|
-
NODE_EP = 1 # end point that is not a child of a router
|
|
138
|
-
ROUTER = 2 # endpoint that is router
|
|
139
|
-
LEAF_EP = 3 # end point that is a child of a router
|
|
140
|
-
|
|
141
|
-
|
|
142
52
|
class TrackingPolicy(mlrun.model.ModelObj):
|
|
143
53
|
"""
|
|
144
54
|
Modified model monitoring configurations. By using TrackingPolicy, the user can apply his model monitoring
|
|
@@ -215,3 +125,125 @@ class TrackingPolicy(mlrun.model.ModelObj):
|
|
|
215
125
|
model_monitoring_constants.EventFieldType.DEFAULT_BATCH_INTERVALS
|
|
216
126
|
] = self.default_batch_intervals.dict()
|
|
217
127
|
return struct
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def get_connection_string(project: str = None):
|
|
131
|
+
"""Get endpoint store connection string from the project secret.
|
|
132
|
+
If wasn't set, take it from the system configurations"""
|
|
133
|
+
if is_running_as_api():
|
|
134
|
+
# Running on API server side
|
|
135
|
+
import mlrun.api.crud.secrets
|
|
136
|
+
import mlrun.common.schemas
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
mlrun.api.crud.secrets.Secrets().get_project_secret(
|
|
140
|
+
project=project,
|
|
141
|
+
provider=mlrun.common.schemas.secret.SecretProviderName.kubernetes,
|
|
142
|
+
allow_secrets_from_k8s=True,
|
|
143
|
+
secret_key=model_monitoring_constants.ProjectSecretKeys.ENDPOINT_STORE_CONNECTION,
|
|
144
|
+
)
|
|
145
|
+
or mlrun.mlconf.model_endpoint_monitoring.endpoint_store_connection
|
|
146
|
+
)
|
|
147
|
+
else:
|
|
148
|
+
# Running on stream server side
|
|
149
|
+
import mlrun
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
mlrun.get_secret_or_env(
|
|
153
|
+
model_monitoring_constants.ProjectSecretKeys.ENDPOINT_STORE_CONNECTION
|
|
154
|
+
)
|
|
155
|
+
or mlrun.mlconf.model_endpoint_monitoring.endpoint_store_connection
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def get_stream_path(project: str = None):
|
|
160
|
+
# TODO: This function (as well as other methods in this file) includes both client and server side code. We will
|
|
161
|
+
# need to refactor and adjust this file in the future.
|
|
162
|
+
"""Get stream path from the project secret. If wasn't set, take it from the system configurations"""
|
|
163
|
+
|
|
164
|
+
if is_running_as_api():
|
|
165
|
+
# Running on API server side
|
|
166
|
+
import mlrun.api.crud.secrets
|
|
167
|
+
import mlrun.common.schemas
|
|
168
|
+
|
|
169
|
+
stream_uri = mlrun.api.crud.secrets.Secrets().get_project_secret(
|
|
170
|
+
project=project,
|
|
171
|
+
provider=mlrun.common.schemas.secret.SecretProviderName.kubernetes,
|
|
172
|
+
allow_secrets_from_k8s=True,
|
|
173
|
+
secret_key=model_monitoring_constants.ProjectSecretKeys.STREAM_PATH,
|
|
174
|
+
) or mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
175
|
+
project=project,
|
|
176
|
+
kind=model_monitoring_constants.FileTargetKind.STREAM,
|
|
177
|
+
target="online",
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
else:
|
|
181
|
+
import mlrun
|
|
182
|
+
|
|
183
|
+
stream_uri = mlrun.get_secret_or_env(
|
|
184
|
+
model_monitoring_constants.ProjectSecretKeys.STREAM_PATH
|
|
185
|
+
) or mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
186
|
+
project=project,
|
|
187
|
+
kind=model_monitoring_constants.FileTargetKind.STREAM,
|
|
188
|
+
target="online",
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
if stream_uri.startswith("kafka://"):
|
|
192
|
+
if "?topic" in stream_uri:
|
|
193
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
194
|
+
"Custom kafka topic is not allowed"
|
|
195
|
+
)
|
|
196
|
+
# Add topic to stream kafka uri
|
|
197
|
+
stream_uri += f"?topic=monitoring_stream_{project}"
|
|
198
|
+
|
|
199
|
+
elif stream_uri.startswith("v3io://") and mlrun.mlconf.is_ce_mode():
|
|
200
|
+
# V3IO is not supported in CE mode, generating a default http stream path
|
|
201
|
+
stream_uri = mlrun.mlconf.model_endpoint_monitoring.default_http_sink
|
|
202
|
+
|
|
203
|
+
return stream_uri
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def validate_old_schema_fields(endpoint: dict):
|
|
207
|
+
"""
|
|
208
|
+
Replace default null values for `error_count` and `metrics` for users that logged a model endpoint before 1.3.0.
|
|
209
|
+
In addition, this function also validates that the key name of the endpoint unique id is `uid` and not
|
|
210
|
+
`endpoint_id` that has been used before 1.3.0.
|
|
211
|
+
|
|
212
|
+
Leaving here for backwards compatibility which related to the model endpoint schema.
|
|
213
|
+
|
|
214
|
+
:param endpoint: An endpoint flattened dictionary.
|
|
215
|
+
"""
|
|
216
|
+
warnings.warn(
|
|
217
|
+
"This will be deprecated in 1.3.0, and will be removed in 1.5.0",
|
|
218
|
+
# TODO: In 1.3.0 do changes in examples & demos In 1.5.0 remove
|
|
219
|
+
FutureWarning,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Validate default value for `error_count`
|
|
223
|
+
# For backwards compatibility reasons, we validate that the model endpoint includes the `error_count` key
|
|
224
|
+
if (
|
|
225
|
+
model_monitoring_constants.EventFieldType.ERROR_COUNT in endpoint
|
|
226
|
+
and endpoint[model_monitoring_constants.EventFieldType.ERROR_COUNT] == "null"
|
|
227
|
+
):
|
|
228
|
+
endpoint[model_monitoring_constants.EventFieldType.ERROR_COUNT] = "0"
|
|
229
|
+
|
|
230
|
+
# Validate default value for `metrics`
|
|
231
|
+
# For backwards compatibility reasons, we validate that the model endpoint includes the `metrics` key
|
|
232
|
+
if (
|
|
233
|
+
model_monitoring_constants.EventFieldType.METRICS in endpoint
|
|
234
|
+
and endpoint[model_monitoring_constants.EventFieldType.METRICS] == "null"
|
|
235
|
+
):
|
|
236
|
+
endpoint[model_monitoring_constants.EventFieldType.METRICS] = json.dumps(
|
|
237
|
+
{
|
|
238
|
+
model_monitoring_constants.EventKeyMetrics.GENERIC: {
|
|
239
|
+
model_monitoring_constants.EventLiveStats.LATENCY_AVG_1H: 0,
|
|
240
|
+
model_monitoring_constants.EventLiveStats.PREDICTIONS_PER_SECOND: 0,
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
# Validate key `uid` instead of `endpoint_id`
|
|
245
|
+
# For backwards compatibility reasons, we replace the `endpoint_id` with `uid` which is the updated key name
|
|
246
|
+
if model_monitoring_constants.EventFieldType.ENDPOINT_ID in endpoint:
|
|
247
|
+
endpoint[model_monitoring_constants.EventFieldType.UID] = endpoint[
|
|
248
|
+
model_monitoring_constants.EventFieldType.ENDPOINT_ID
|
|
249
|
+
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
import enum
|
|
16
16
|
import typing
|
|
17
17
|
|
|
18
|
-
from .
|
|
18
|
+
from mlrun.common.schemas.notification import NotificationKind
|
|
19
|
+
|
|
20
|
+
from .base import NotificationBase
|
|
19
21
|
from .console import ConsoleNotification
|
|
20
22
|
from .git import GitNotification
|
|
21
23
|
from .ipython import IPythonNotification
|
|
@@ -23,10 +25,10 @@ from .slack import SlackNotification
|
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
class NotificationTypes(str, enum.Enum):
|
|
26
|
-
console =
|
|
27
|
-
git =
|
|
28
|
-
ipython =
|
|
29
|
-
slack =
|
|
28
|
+
console = NotificationKind.console.value
|
|
29
|
+
git = NotificationKind.git.value
|
|
30
|
+
ipython = NotificationKind.ipython.value
|
|
31
|
+
slack = NotificationKind.slack.value
|
|
30
32
|
|
|
31
33
|
def get_notification(self) -> typing.Type[NotificationBase]:
|
|
32
34
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -12,35 +12,36 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import
|
|
15
|
+
import asyncio
|
|
16
16
|
import typing
|
|
17
17
|
|
|
18
|
+
import mlrun.common.schemas
|
|
18
19
|
import mlrun.lists
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
class NotificationSeverity(str, enum.Enum):
|
|
22
|
-
INFO = "info"
|
|
23
|
-
DEBUG = "debug"
|
|
24
|
-
VERBOSE = "verbose"
|
|
25
|
-
WARNING = "warning"
|
|
26
|
-
ERROR = "error"
|
|
27
|
-
|
|
28
|
-
|
|
29
22
|
class NotificationBase:
|
|
30
23
|
def __init__(
|
|
31
24
|
self,
|
|
25
|
+
name: str = None,
|
|
32
26
|
params: typing.Dict[str, str] = None,
|
|
33
27
|
):
|
|
28
|
+
self.name = name
|
|
34
29
|
self.params = params or {}
|
|
35
30
|
|
|
36
31
|
@property
|
|
37
32
|
def active(self) -> bool:
|
|
38
33
|
return True
|
|
39
34
|
|
|
40
|
-
|
|
35
|
+
@property
|
|
36
|
+
def is_async(self) -> bool:
|
|
37
|
+
return asyncio.iscoroutinefunction(self.push)
|
|
38
|
+
|
|
39
|
+
def push(
|
|
41
40
|
self,
|
|
42
41
|
message: str,
|
|
43
|
-
severity: typing.Union[
|
|
42
|
+
severity: typing.Union[
|
|
43
|
+
mlrun.common.schemas.NotificationSeverity, str
|
|
44
|
+
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
44
45
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
45
46
|
custom_html: str = None,
|
|
46
47
|
):
|
|
@@ -52,16 +53,21 @@ class NotificationBase:
|
|
|
52
53
|
) -> None:
|
|
53
54
|
self.params = params or {}
|
|
54
55
|
|
|
55
|
-
@staticmethod
|
|
56
56
|
def _get_html(
|
|
57
|
+
self,
|
|
57
58
|
message: str,
|
|
58
|
-
severity: typing.Union[
|
|
59
|
+
severity: typing.Union[
|
|
60
|
+
mlrun.common.schemas.NotificationSeverity, str
|
|
61
|
+
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
59
62
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
60
63
|
custom_html: str = None,
|
|
61
64
|
) -> str:
|
|
62
65
|
if custom_html:
|
|
63
66
|
return custom_html
|
|
64
67
|
|
|
68
|
+
if self.name:
|
|
69
|
+
message = f"{self.name}: {message}"
|
|
70
|
+
|
|
65
71
|
if not runs:
|
|
66
72
|
return f"[{severity}] {message}"
|
|
67
73
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -16,10 +16,11 @@ import typing
|
|
|
16
16
|
|
|
17
17
|
import tabulate
|
|
18
18
|
|
|
19
|
+
import mlrun.common.schemas
|
|
19
20
|
import mlrun.lists
|
|
20
21
|
import mlrun.utils.helpers
|
|
21
22
|
|
|
22
|
-
from .base import NotificationBase
|
|
23
|
+
from .base import NotificationBase
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class ConsoleNotification(NotificationBase):
|
|
@@ -27,10 +28,12 @@ class ConsoleNotification(NotificationBase):
|
|
|
27
28
|
Client only notification for printing run status notifications in console
|
|
28
29
|
"""
|
|
29
30
|
|
|
30
|
-
def
|
|
31
|
+
def push(
|
|
31
32
|
self,
|
|
32
33
|
message: str,
|
|
33
|
-
severity: typing.Union[
|
|
34
|
+
severity: typing.Union[
|
|
35
|
+
mlrun.common.schemas.NotificationSeverity, str
|
|
36
|
+
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
34
37
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
35
38
|
custom_html: str = None,
|
|
36
39
|
):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -16,12 +16,13 @@ import json
|
|
|
16
16
|
import os
|
|
17
17
|
import typing
|
|
18
18
|
|
|
19
|
-
import
|
|
19
|
+
import aiohttp
|
|
20
20
|
|
|
21
|
+
import mlrun.common.schemas
|
|
21
22
|
import mlrun.errors
|
|
22
23
|
import mlrun.lists
|
|
23
24
|
|
|
24
|
-
from .base import NotificationBase
|
|
25
|
+
from .base import NotificationBase
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class GitNotification(NotificationBase):
|
|
@@ -29,15 +30,18 @@ class GitNotification(NotificationBase):
|
|
|
29
30
|
API/Client notification for setting a rich run statuses git issue comment (github/gitlab)
|
|
30
31
|
"""
|
|
31
32
|
|
|
32
|
-
def
|
|
33
|
+
async def push(
|
|
33
34
|
self,
|
|
34
35
|
message: str,
|
|
35
|
-
severity: typing.Union[
|
|
36
|
+
severity: typing.Union[
|
|
37
|
+
mlrun.common.schemas.NotificationSeverity, str
|
|
38
|
+
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
36
39
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
37
40
|
custom_html: str = None,
|
|
38
41
|
):
|
|
39
42
|
git_repo = self.params.get("repo", None)
|
|
40
43
|
git_issue = self.params.get("issue", None)
|
|
44
|
+
git_merge_request = self.params.get("merge_request", None)
|
|
41
45
|
token = (
|
|
42
46
|
self.params.get("token", None)
|
|
43
47
|
or self.params.get("GIT_TOKEN", None)
|
|
@@ -45,20 +49,22 @@ class GitNotification(NotificationBase):
|
|
|
45
49
|
)
|
|
46
50
|
server = self.params.get("server", None)
|
|
47
51
|
gitlab = self.params.get("gitlab", False)
|
|
48
|
-
self._pr_comment(
|
|
52
|
+
await self._pr_comment(
|
|
49
53
|
self._get_html(message, severity, runs, custom_html),
|
|
50
54
|
git_repo,
|
|
51
55
|
git_issue,
|
|
56
|
+
merge_request=git_merge_request,
|
|
52
57
|
token=token,
|
|
53
58
|
server=server,
|
|
54
59
|
gitlab=gitlab,
|
|
55
60
|
)
|
|
56
61
|
|
|
57
62
|
@staticmethod
|
|
58
|
-
def _pr_comment(
|
|
63
|
+
async def _pr_comment(
|
|
59
64
|
message: str,
|
|
60
65
|
repo: str = None,
|
|
61
66
|
issue: int = None,
|
|
67
|
+
merge_request: int = None,
|
|
62
68
|
token: str = None,
|
|
63
69
|
server: str = None,
|
|
64
70
|
gitlab: bool = False,
|
|
@@ -86,12 +92,19 @@ class GitNotification(NotificationBase):
|
|
|
86
92
|
headers = {"PRIVATE-TOKEN": token}
|
|
87
93
|
repo = repo or os.environ.get("CI_PROJECT_ID")
|
|
88
94
|
# auto detect GitLab pr id from the environment
|
|
89
|
-
issue = issue or os.environ.get("
|
|
95
|
+
issue = issue or os.environ.get("CI_ISSUE_IID")
|
|
96
|
+
merge_request = merge_request or os.environ.get("CI_MERGE_REQUEST_IID")
|
|
90
97
|
# replace slash with url encoded slash for GitLab to accept a repo name with slash
|
|
91
98
|
repo = repo.replace("/", "%2F")
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
99
|
+
|
|
100
|
+
if merge_request:
|
|
101
|
+
url = f"https://{server}/api/v4/projects/{repo}/merge_requests/{merge_request}/notes"
|
|
102
|
+
elif issue:
|
|
103
|
+
url = f"https://{server}/api/v4/projects/{repo}/issues/{issue}/notes"
|
|
104
|
+
else:
|
|
105
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
106
|
+
"GitLab issue or merge request id not specified"
|
|
107
|
+
)
|
|
95
108
|
else:
|
|
96
109
|
server = server or "api.github.com"
|
|
97
110
|
repo = repo or os.environ.get("GITHUB_REPOSITORY")
|
|
@@ -101,19 +114,23 @@ class GitNotification(NotificationBase):
|
|
|
101
114
|
with open(os.environ["GITHUB_EVENT_PATH"]) as fp:
|
|
102
115
|
data = fp.read()
|
|
103
116
|
event = json.loads(data)
|
|
104
|
-
if "
|
|
117
|
+
if "number" not in event:
|
|
105
118
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
106
119
|
f"issue not found in github actions event\ndata={data}"
|
|
107
120
|
)
|
|
108
|
-
issue = event["
|
|
121
|
+
issue = event["number"]
|
|
109
122
|
headers = {
|
|
110
123
|
"Accept": "application/vnd.github.v3+json",
|
|
111
124
|
"Authorization": f"token {token}",
|
|
112
125
|
}
|
|
113
126
|
url = f"https://{server}/repos/{repo}/issues/{issue}/comments"
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
127
|
+
|
|
128
|
+
async with aiohttp.ClientSession() as session:
|
|
129
|
+
resp = await session.post(url, headers=headers, json={"body": message})
|
|
130
|
+
if not resp.ok:
|
|
131
|
+
resp_text = await resp.text()
|
|
132
|
+
raise mlrun.errors.MLRunBadRequestError(
|
|
133
|
+
f"Failed commenting on PR: {resp_text}"
|
|
134
|
+
)
|
|
135
|
+
data = await resp.json()
|
|
136
|
+
return data.get("id")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
|
|
15
15
|
import typing
|
|
16
16
|
|
|
17
|
+
import mlrun.common.schemas
|
|
17
18
|
import mlrun.lists
|
|
18
19
|
import mlrun.utils.helpers
|
|
19
20
|
|
|
20
|
-
from .base import NotificationBase
|
|
21
|
+
from .base import NotificationBase
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class IPythonNotification(NotificationBase):
|
|
@@ -27,16 +28,15 @@ class IPythonNotification(NotificationBase):
|
|
|
27
28
|
|
|
28
29
|
def __init__(
|
|
29
30
|
self,
|
|
31
|
+
name: str = None,
|
|
30
32
|
params: typing.Dict[str, str] = None,
|
|
31
33
|
):
|
|
32
|
-
super().__init__(params)
|
|
34
|
+
super().__init__(name, params)
|
|
33
35
|
self._ipython = None
|
|
34
36
|
try:
|
|
35
37
|
import IPython
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
# if its IPython terminal ignore (can't show html)
|
|
39
|
-
if ipy and "Terminal" not in str(type(ipy)):
|
|
39
|
+
if mlrun.utils.helpers.is_running_in_jupyter_notebook():
|
|
40
40
|
self._ipython = IPython
|
|
41
41
|
except ImportError:
|
|
42
42
|
pass
|
|
@@ -45,10 +45,12 @@ class IPythonNotification(NotificationBase):
|
|
|
45
45
|
def active(self) -> bool:
|
|
46
46
|
return self._ipython is not None
|
|
47
47
|
|
|
48
|
-
def
|
|
48
|
+
def push(
|
|
49
49
|
self,
|
|
50
50
|
message: str,
|
|
51
|
-
severity: typing.Union[
|
|
51
|
+
severity: typing.Union[
|
|
52
|
+
mlrun.common.schemas.NotificationSeverity, str
|
|
53
|
+
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
52
54
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
53
55
|
custom_html: str = None,
|
|
54
56
|
):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import json
|
|
16
15
|
import typing
|
|
17
16
|
|
|
18
|
-
import
|
|
17
|
+
import aiohttp
|
|
19
18
|
|
|
19
|
+
import mlrun.common.schemas
|
|
20
20
|
import mlrun.lists
|
|
21
21
|
import mlrun.utils.helpers
|
|
22
22
|
|
|
23
|
-
from .base import NotificationBase
|
|
23
|
+
from .base import NotificationBase
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class SlackNotification(NotificationBase):
|
|
@@ -34,10 +34,12 @@ class SlackNotification(NotificationBase):
|
|
|
34
34
|
"error": ":x:",
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
def
|
|
37
|
+
async def push(
|
|
38
38
|
self,
|
|
39
39
|
message: str,
|
|
40
|
-
severity: typing.Union[
|
|
40
|
+
severity: typing.Union[
|
|
41
|
+
mlrun.common.schemas.NotificationSeverity, str
|
|
42
|
+
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
41
43
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
42
44
|
custom_html: str = None,
|
|
43
45
|
):
|
|
@@ -53,17 +55,16 @@ class SlackNotification(NotificationBase):
|
|
|
53
55
|
|
|
54
56
|
data = self._generate_slack_data(message, severity, runs)
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
webhook,
|
|
58
|
-
|
|
59
|
-
headers={"Content-Type": "application/json"},
|
|
60
|
-
)
|
|
61
|
-
response.raise_for_status()
|
|
58
|
+
async with aiohttp.ClientSession() as session:
|
|
59
|
+
async with session.post(webhook, json=data) as response:
|
|
60
|
+
response.raise_for_status()
|
|
62
61
|
|
|
63
62
|
def _generate_slack_data(
|
|
64
63
|
self,
|
|
65
64
|
message: str,
|
|
66
|
-
severity: typing.Union[
|
|
65
|
+
severity: typing.Union[
|
|
66
|
+
mlrun.common.schemas.NotificationSeverity, str
|
|
67
|
+
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
67
68
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
68
69
|
) -> dict:
|
|
69
70
|
data = {
|
|
@@ -74,6 +75,10 @@ class SlackNotification(NotificationBase):
|
|
|
74
75
|
},
|
|
75
76
|
]
|
|
76
77
|
}
|
|
78
|
+
if self.name:
|
|
79
|
+
data["blocks"].append(
|
|
80
|
+
{"type": "section", "text": self._get_slack_row(self.name)}
|
|
81
|
+
)
|
|
77
82
|
|
|
78
83
|
if not runs:
|
|
79
84
|
return data
|