mlrun 1.3.3__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.3.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.3.dist-info/RECORD +0 -381
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/LICENSE +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/WHEEL +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/entry_points.txt +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,310 @@
|
|
|
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 urllib.parse
|
|
16
|
+
|
|
17
|
+
import semver
|
|
18
|
+
|
|
19
|
+
import mlrun
|
|
20
|
+
import mlrun.api.utils.singletons.k8s
|
|
21
|
+
import mlrun.runtimes
|
|
22
|
+
from mlrun.utils import logger
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def resolve_function_http_trigger(function_spec):
|
|
26
|
+
for trigger_name, trigger_config in function_spec.get("triggers", {}).items():
|
|
27
|
+
if trigger_config.get("kind") != "http":
|
|
28
|
+
continue
|
|
29
|
+
return trigger_config
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def resolve_nuclio_runtime_python_image(
|
|
33
|
+
mlrun_client_version: str = None, python_version: str = None
|
|
34
|
+
):
|
|
35
|
+
# if no python version or mlrun version is passed it means we use mlrun client older than 1.3.0 therefore need
|
|
36
|
+
# to use the previoud default runtime which is python 3.7
|
|
37
|
+
if not python_version or not mlrun_client_version:
|
|
38
|
+
return "python:3.7"
|
|
39
|
+
|
|
40
|
+
# If the mlrun version is 0.0.0-<unstable>, it is a dev version,
|
|
41
|
+
# so we can't check if it is higher than 1.3.0, but if the python version was passed,
|
|
42
|
+
# it means it is 1.3.0-rc or higher, so use the image according to the python version
|
|
43
|
+
if mlrun_client_version.startswith("0.0.0-") or "unstable" in mlrun_client_version:
|
|
44
|
+
if python_version.startswith("3.7"):
|
|
45
|
+
return "python:3.7"
|
|
46
|
+
|
|
47
|
+
return mlrun.mlconf.default_nuclio_runtime
|
|
48
|
+
|
|
49
|
+
# if mlrun version is older than 1.3.0 we need to use the previous default runtime which is python 3.7
|
|
50
|
+
if semver.VersionInfo.parse(mlrun_client_version) < semver.VersionInfo.parse(
|
|
51
|
+
"1.3.0-X"
|
|
52
|
+
):
|
|
53
|
+
return "python:3.7"
|
|
54
|
+
|
|
55
|
+
# if mlrun version is 1.3.0 or newer and python version is 3.7 we need to use python 3.7 image
|
|
56
|
+
if semver.VersionInfo.parse(mlrun_client_version) >= semver.VersionInfo.parse(
|
|
57
|
+
"1.3.0-X"
|
|
58
|
+
) and python_version.startswith("3.7"):
|
|
59
|
+
return "python:3.7"
|
|
60
|
+
|
|
61
|
+
# if none of the above conditions are met we use the default runtime which is python 3.9
|
|
62
|
+
return mlrun.mlconf.default_nuclio_runtime
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def resolve_function_ingresses(function_spec):
|
|
66
|
+
http_trigger = resolve_function_http_trigger(function_spec)
|
|
67
|
+
if not http_trigger:
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
ingresses = []
|
|
71
|
+
for _, ingress_config in (
|
|
72
|
+
http_trigger.get("attributes", {}).get("ingresses", {}).items()
|
|
73
|
+
):
|
|
74
|
+
ingresses.append(ingress_config)
|
|
75
|
+
return ingresses
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def enrich_function_with_ingress(config, mode, service_type):
|
|
79
|
+
# do not enrich with an ingress
|
|
80
|
+
if mode == mlrun.runtimes.constants.NuclioIngressAddTemplatedIngressModes.never:
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
ingresses = resolve_function_ingresses(config["spec"])
|
|
84
|
+
|
|
85
|
+
# function has ingresses already, nothing to add / enrich
|
|
86
|
+
if ingresses:
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
# if exists, get the http trigger the function has
|
|
90
|
+
# we would enrich it with an ingress
|
|
91
|
+
http_trigger = resolve_function_http_trigger(config["spec"])
|
|
92
|
+
if not http_trigger:
|
|
93
|
+
# function has an HTTP trigger without an ingress
|
|
94
|
+
# TODO: read from nuclio-api frontend-spec
|
|
95
|
+
http_trigger = {
|
|
96
|
+
"kind": "http",
|
|
97
|
+
"name": "http",
|
|
98
|
+
"maxWorkers": 1,
|
|
99
|
+
"workerAvailabilityTimeoutMilliseconds": 10000, # 10 seconds
|
|
100
|
+
"attributes": {},
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
def enrich():
|
|
104
|
+
http_trigger.setdefault("attributes", {}).setdefault("ingresses", {})["0"] = {
|
|
105
|
+
"paths": ["/"],
|
|
106
|
+
# this would tell Nuclio to use its default ingress host template
|
|
107
|
+
# and would auto assign a host for the ingress
|
|
108
|
+
"hostTemplate": "@nuclio.fromDefault",
|
|
109
|
+
}
|
|
110
|
+
http_trigger["attributes"]["serviceType"] = service_type
|
|
111
|
+
config["spec"].setdefault("triggers", {})[http_trigger["name"]] = http_trigger
|
|
112
|
+
|
|
113
|
+
if mode == mlrun.runtimes.constants.NuclioIngressAddTemplatedIngressModes.always:
|
|
114
|
+
enrich()
|
|
115
|
+
elif (
|
|
116
|
+
mode
|
|
117
|
+
== mlrun.runtimes.constants.NuclioIngressAddTemplatedIngressModes.on_cluster_ip
|
|
118
|
+
):
|
|
119
|
+
|
|
120
|
+
# service type is not cluster ip, bail out
|
|
121
|
+
if service_type and service_type.lower() != "clusterip":
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
enrich()
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def resolve_function_image_pull_secret(function):
|
|
128
|
+
"""
|
|
129
|
+
the corresponding attribute for 'build.secret' in nuclio is imagePullSecrets, attached link for reference
|
|
130
|
+
https://github.com/nuclio/nuclio/blob/e4af2a000dc52ee17337e75181ecb2652b9bf4e5/pkg/processor/build/builder.go#L1073
|
|
131
|
+
if only one of the secrets is set, use it.
|
|
132
|
+
if both are set, use the non default one and give precedence to image_pull_secret
|
|
133
|
+
"""
|
|
134
|
+
# enrich only on server side
|
|
135
|
+
if not mlrun.config.is_running_as_api():
|
|
136
|
+
return function.spec.image_pull_secret or function.spec.build.secret
|
|
137
|
+
|
|
138
|
+
if function.spec.image_pull_secret is None:
|
|
139
|
+
function.spec.image_pull_secret = (
|
|
140
|
+
mlrun.mlconf.function.spec.image_pull_secret.default
|
|
141
|
+
)
|
|
142
|
+
elif (
|
|
143
|
+
function.spec.image_pull_secret
|
|
144
|
+
!= mlrun.mlconf.function.spec.image_pull_secret.default
|
|
145
|
+
):
|
|
146
|
+
return function.spec.image_pull_secret
|
|
147
|
+
|
|
148
|
+
if function.spec.build.secret is None:
|
|
149
|
+
function.spec.build.secret = mlrun.mlconf.httpdb.builder.docker_registry_secret
|
|
150
|
+
elif (
|
|
151
|
+
function.spec.build.secret != mlrun.mlconf.httpdb.builder.docker_registry_secret
|
|
152
|
+
):
|
|
153
|
+
return function.spec.build.secret
|
|
154
|
+
|
|
155
|
+
return function.spec.image_pull_secret or function.spec.build.secret
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def resolve_work_dir_and_handler(handler):
|
|
159
|
+
"""
|
|
160
|
+
Resolves a nuclio function working dir and handler inside an archive/git repo
|
|
161
|
+
:param handler: a path describing working dir and handler of a nuclio function
|
|
162
|
+
:return: (working_dir, handler) tuple, as nuclio expects to get it
|
|
163
|
+
|
|
164
|
+
Example: ("a/b/c#main:Handler") -> ("a/b/c", "main:Handler")
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def extend_handler(base_handler):
|
|
168
|
+
# return default handler and module if not specified
|
|
169
|
+
if not base_handler:
|
|
170
|
+
return "main:handler"
|
|
171
|
+
if ":" not in base_handler:
|
|
172
|
+
base_handler = f"{base_handler}:handler"
|
|
173
|
+
return base_handler
|
|
174
|
+
|
|
175
|
+
if not handler:
|
|
176
|
+
return "", "main:handler"
|
|
177
|
+
|
|
178
|
+
split_handler = handler.split("#")
|
|
179
|
+
if len(split_handler) == 1:
|
|
180
|
+
return "", extend_handler(handler)
|
|
181
|
+
|
|
182
|
+
return split_handler[0], extend_handler(split_handler[1])
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def is_nuclio_version_in_range(min_version: str, max_version: str) -> bool:
|
|
186
|
+
"""
|
|
187
|
+
Return whether the Nuclio version is in the range, inclusive for min, exclusive for max - [min, max)
|
|
188
|
+
"""
|
|
189
|
+
resolved_nuclio_version = None
|
|
190
|
+
try:
|
|
191
|
+
parsed_min_version = semver.VersionInfo.parse(min_version)
|
|
192
|
+
parsed_max_version = semver.VersionInfo.parse(max_version)
|
|
193
|
+
resolved_nuclio_version = mlrun.runtimes.utils.resolve_nuclio_version()
|
|
194
|
+
parsed_current_version = semver.VersionInfo.parse(resolved_nuclio_version)
|
|
195
|
+
except ValueError:
|
|
196
|
+
logger.warning(
|
|
197
|
+
"Unable to parse nuclio version, assuming in range",
|
|
198
|
+
nuclio_version=resolved_nuclio_version,
|
|
199
|
+
min_version=min_version,
|
|
200
|
+
max_version=max_version,
|
|
201
|
+
)
|
|
202
|
+
return True
|
|
203
|
+
return parsed_min_version <= parsed_current_version < parsed_max_version
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def compile_nuclio_archive_config(
|
|
207
|
+
nuclio_spec,
|
|
208
|
+
function: mlrun.runtimes.function.RemoteRuntime,
|
|
209
|
+
builder_env,
|
|
210
|
+
project=None,
|
|
211
|
+
auth_info=None,
|
|
212
|
+
):
|
|
213
|
+
secrets = {}
|
|
214
|
+
if (
|
|
215
|
+
project
|
|
216
|
+
and mlrun.api.utils.singletons.k8s.get_k8s_helper().is_running_inside_kubernetes_cluster()
|
|
217
|
+
):
|
|
218
|
+
secrets = (
|
|
219
|
+
mlrun.api.utils.singletons.k8s.get_k8s_helper().get_project_secret_data(
|
|
220
|
+
project
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
def get_secret(key):
|
|
225
|
+
return builder_env.get(key) or secrets.get(key, "")
|
|
226
|
+
|
|
227
|
+
source = function.spec.build.source
|
|
228
|
+
parsed_url = urllib.parse.urlparse(source)
|
|
229
|
+
code_entry_type = ""
|
|
230
|
+
if source.startswith("s3://"):
|
|
231
|
+
code_entry_type = "s3"
|
|
232
|
+
if source.startswith("git://"):
|
|
233
|
+
code_entry_type = "git"
|
|
234
|
+
for archive_prefix in ["http://", "https://", "v3io://", "v3ios://"]:
|
|
235
|
+
if source.startswith(archive_prefix):
|
|
236
|
+
code_entry_type = "archive"
|
|
237
|
+
|
|
238
|
+
if code_entry_type == "":
|
|
239
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
240
|
+
"Couldn't resolve code entry type from source"
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
code_entry_attributes = {}
|
|
244
|
+
|
|
245
|
+
# resolve work_dir and handler
|
|
246
|
+
work_dir, handler = resolve_work_dir_and_handler(function.spec.function_handler)
|
|
247
|
+
work_dir = function.spec.workdir or work_dir
|
|
248
|
+
if work_dir != "":
|
|
249
|
+
code_entry_attributes["workDir"] = work_dir
|
|
250
|
+
|
|
251
|
+
# archive
|
|
252
|
+
if code_entry_type == "archive":
|
|
253
|
+
v3io_access_key = builder_env.get("V3IO_ACCESS_KEY", "")
|
|
254
|
+
if source.startswith("v3io"):
|
|
255
|
+
if not parsed_url.netloc:
|
|
256
|
+
source = mlrun.mlconf.v3io_api + parsed_url.path
|
|
257
|
+
else:
|
|
258
|
+
source = f"http{source[len('v3io'):]}"
|
|
259
|
+
if auth_info and not v3io_access_key:
|
|
260
|
+
v3io_access_key = auth_info.data_session or auth_info.access_key
|
|
261
|
+
|
|
262
|
+
if v3io_access_key:
|
|
263
|
+
code_entry_attributes["headers"] = {"X-V3io-Session-Key": v3io_access_key}
|
|
264
|
+
|
|
265
|
+
# s3
|
|
266
|
+
if code_entry_type == "s3":
|
|
267
|
+
bucket, item_key = mlrun.datastore.parse_s3_bucket_and_key(source)
|
|
268
|
+
|
|
269
|
+
code_entry_attributes["s3Bucket"] = bucket
|
|
270
|
+
code_entry_attributes["s3ItemKey"] = item_key
|
|
271
|
+
|
|
272
|
+
code_entry_attributes["s3AccessKeyId"] = get_secret("AWS_ACCESS_KEY_ID")
|
|
273
|
+
code_entry_attributes["s3SecretAccessKey"] = get_secret("AWS_SECRET_ACCESS_KEY")
|
|
274
|
+
code_entry_attributes["s3SessionToken"] = get_secret("AWS_SESSION_TOKEN")
|
|
275
|
+
|
|
276
|
+
# git
|
|
277
|
+
if code_entry_type == "git":
|
|
278
|
+
|
|
279
|
+
# change git:// to https:// as nuclio expects it to be
|
|
280
|
+
if source.startswith("git://"):
|
|
281
|
+
source = source.replace("git://", "https://")
|
|
282
|
+
|
|
283
|
+
source, reference, branch = mlrun.utils.resolve_git_reference_from_source(
|
|
284
|
+
source
|
|
285
|
+
)
|
|
286
|
+
if not branch and not reference:
|
|
287
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
288
|
+
"git branch or refs must be specified in the source e.g.: "
|
|
289
|
+
"'git://<url>/org/repo.git#<branch-name or refs/heads/..>'"
|
|
290
|
+
)
|
|
291
|
+
if reference:
|
|
292
|
+
code_entry_attributes["reference"] = reference
|
|
293
|
+
if branch:
|
|
294
|
+
code_entry_attributes["branch"] = branch
|
|
295
|
+
|
|
296
|
+
password = get_secret("GIT_PASSWORD")
|
|
297
|
+
username = get_secret("GIT_USERNAME")
|
|
298
|
+
|
|
299
|
+
token = get_secret("GIT_TOKEN")
|
|
300
|
+
if token:
|
|
301
|
+
username, password = mlrun.utils.get_git_username_password_from_token(token)
|
|
302
|
+
|
|
303
|
+
code_entry_attributes["username"] = username
|
|
304
|
+
code_entry_attributes["password"] = password
|
|
305
|
+
|
|
306
|
+
# populate spec with relevant fields
|
|
307
|
+
nuclio_spec.set_config("spec.handler", handler)
|
|
308
|
+
nuclio_spec.set_config("spec.build.path", source)
|
|
309
|
+
nuclio_spec.set_config("spec.build.codeEntryType", code_entry_type)
|
|
310
|
+
nuclio_spec.set_config("spec.build.codeEntryAttributes", code_entry_attributes)
|
mlrun/api/crud/secrets.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.
|
|
@@ -17,8 +17,10 @@ import json
|
|
|
17
17
|
import typing
|
|
18
18
|
import uuid
|
|
19
19
|
|
|
20
|
-
import mlrun.api.
|
|
20
|
+
import mlrun.api.utils.clients.iguazio
|
|
21
|
+
import mlrun.api.utils.events.events_factory as events_factory
|
|
21
22
|
import mlrun.api.utils.singletons.k8s
|
|
23
|
+
import mlrun.common.schemas
|
|
22
24
|
import mlrun.errors
|
|
23
25
|
import mlrun.utils.helpers
|
|
24
26
|
import mlrun.utils.regex
|
|
@@ -30,7 +32,8 @@ class SecretsClientType(str, enum.Enum):
|
|
|
30
32
|
schedules = "schedules"
|
|
31
33
|
model_monitoring = "model-monitoring"
|
|
32
34
|
service_accounts = "service-accounts"
|
|
33
|
-
|
|
35
|
+
hub = "hub"
|
|
36
|
+
notifications = "notifications"
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
class Secrets(
|
|
@@ -73,7 +76,7 @@ class Secrets(
|
|
|
73
76
|
def store_project_secrets(
|
|
74
77
|
self,
|
|
75
78
|
project: str,
|
|
76
|
-
secrets: mlrun.
|
|
79
|
+
secrets: mlrun.common.schemas.SecretsData,
|
|
77
80
|
allow_internal_secrets: bool = False,
|
|
78
81
|
key_map_secret_key: typing.Optional[str] = None,
|
|
79
82
|
allow_storing_key_maps: bool = False,
|
|
@@ -93,18 +96,33 @@ class Secrets(
|
|
|
93
96
|
allow_storing_key_maps,
|
|
94
97
|
)
|
|
95
98
|
|
|
96
|
-
if secrets.provider == mlrun.
|
|
99
|
+
if secrets.provider == mlrun.common.schemas.SecretProviderName.vault:
|
|
97
100
|
# Init is idempotent and will do nothing if infra is already in place
|
|
98
101
|
mlrun.utils.vault.init_project_vault_configuration(project)
|
|
99
102
|
|
|
100
103
|
# If no secrets were passed, no need to touch the actual secrets.
|
|
101
104
|
if secrets_to_store:
|
|
102
105
|
mlrun.utils.vault.store_vault_project_secrets(project, secrets_to_store)
|
|
103
|
-
elif secrets.provider == mlrun.
|
|
104
|
-
if mlrun.api.utils.singletons.k8s.
|
|
105
|
-
|
|
106
|
+
elif secrets.provider == mlrun.common.schemas.SecretProviderName.kubernetes:
|
|
107
|
+
if mlrun.api.utils.singletons.k8s.get_k8s_helper():
|
|
108
|
+
(
|
|
109
|
+
secret_name,
|
|
110
|
+
action,
|
|
111
|
+
) = mlrun.api.utils.singletons.k8s.get_k8s_helper().store_project_secrets(
|
|
106
112
|
project, secrets_to_store
|
|
107
113
|
)
|
|
114
|
+
secret_keys = [secret_name for secret_name in secrets_to_store.keys()]
|
|
115
|
+
|
|
116
|
+
if action:
|
|
117
|
+
events_client = events_factory.EventsFactory().get_events_client()
|
|
118
|
+
event = events_client.generate_project_secret_event(
|
|
119
|
+
project=project,
|
|
120
|
+
secret_name=secret_name,
|
|
121
|
+
secret_keys=secret_keys,
|
|
122
|
+
action=action,
|
|
123
|
+
)
|
|
124
|
+
events_client.emit(event)
|
|
125
|
+
|
|
108
126
|
else:
|
|
109
127
|
raise mlrun.errors.MLRunInternalServerError(
|
|
110
128
|
"K8s provider cannot be initialized"
|
|
@@ -116,54 +134,61 @@ class Secrets(
|
|
|
116
134
|
|
|
117
135
|
def read_auth_secret(
|
|
118
136
|
self, secret_name, raise_on_not_found=False
|
|
119
|
-
) -> mlrun.
|
|
137
|
+
) -> mlrun.common.schemas.AuthSecretData:
|
|
120
138
|
(
|
|
121
139
|
username,
|
|
122
140
|
access_key,
|
|
123
|
-
) = mlrun.api.utils.singletons.k8s.
|
|
141
|
+
) = mlrun.api.utils.singletons.k8s.get_k8s_helper().read_auth_secret(
|
|
124
142
|
secret_name, raise_on_not_found=raise_on_not_found
|
|
125
143
|
)
|
|
126
|
-
return mlrun.
|
|
127
|
-
provider=mlrun.
|
|
144
|
+
return mlrun.common.schemas.AuthSecretData(
|
|
145
|
+
provider=mlrun.common.schemas.SecretProviderName.kubernetes,
|
|
128
146
|
username=username,
|
|
129
147
|
access_key=access_key,
|
|
130
148
|
)
|
|
131
149
|
|
|
132
150
|
def store_auth_secret(
|
|
133
151
|
self,
|
|
134
|
-
secret: mlrun.
|
|
152
|
+
secret: mlrun.common.schemas.AuthSecretData,
|
|
135
153
|
) -> str:
|
|
136
|
-
if secret.provider != mlrun.
|
|
154
|
+
if secret.provider != mlrun.common.schemas.SecretProviderName.kubernetes:
|
|
137
155
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
138
156
|
f"Storing auth secret is not implemented for provider {secret.provider}"
|
|
139
157
|
)
|
|
140
|
-
if not mlrun.api.utils.singletons.k8s.
|
|
158
|
+
if not mlrun.api.utils.singletons.k8s.get_k8s_helper():
|
|
141
159
|
raise mlrun.errors.MLRunInternalServerError(
|
|
142
160
|
"K8s provider cannot be initialized"
|
|
143
161
|
)
|
|
144
|
-
|
|
162
|
+
|
|
163
|
+
# ignore the returned action as we don't need to emit an event for auth secrets (they are internal)
|
|
164
|
+
(
|
|
165
|
+
auth_secret_name,
|
|
166
|
+
_,
|
|
167
|
+
) = mlrun.api.utils.singletons.k8s.get_k8s_helper().store_auth_secret(
|
|
145
168
|
secret.username, secret.access_key
|
|
146
169
|
)
|
|
147
170
|
|
|
171
|
+
return auth_secret_name
|
|
172
|
+
|
|
148
173
|
def delete_auth_secret(
|
|
149
174
|
self,
|
|
150
|
-
provider: mlrun.
|
|
175
|
+
provider: mlrun.common.schemas.SecretProviderName,
|
|
151
176
|
secret_name: str,
|
|
152
177
|
):
|
|
153
|
-
if provider != mlrun.
|
|
178
|
+
if provider != mlrun.common.schemas.SecretProviderName.kubernetes:
|
|
154
179
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
155
180
|
f"Storing auth secret is not implemented for provider {provider}"
|
|
156
181
|
)
|
|
157
|
-
if not mlrun.api.utils.singletons.k8s.
|
|
182
|
+
if not mlrun.api.utils.singletons.k8s.get_k8s_helper():
|
|
158
183
|
raise mlrun.errors.MLRunInternalServerError(
|
|
159
184
|
"K8s provider cannot be initialized"
|
|
160
185
|
)
|
|
161
|
-
mlrun.api.utils.singletons.k8s.
|
|
186
|
+
mlrun.api.utils.singletons.k8s.get_k8s_helper().delete_auth_secret(secret_name)
|
|
162
187
|
|
|
163
188
|
def delete_project_secrets(
|
|
164
189
|
self,
|
|
165
190
|
project: str,
|
|
166
|
-
provider: mlrun.
|
|
191
|
+
provider: mlrun.common.schemas.SecretProviderName,
|
|
167
192
|
secrets: typing.Optional[typing.List[str]] = None,
|
|
168
193
|
allow_internal_secrets: bool = False,
|
|
169
194
|
):
|
|
@@ -185,15 +210,29 @@ class Secrets(
|
|
|
185
210
|
# nothing to remove - return
|
|
186
211
|
return
|
|
187
212
|
|
|
188
|
-
if provider == mlrun.
|
|
213
|
+
if provider == mlrun.common.schemas.SecretProviderName.vault:
|
|
189
214
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
190
215
|
f"Delete secret is not implemented for provider {provider}"
|
|
191
216
|
)
|
|
192
|
-
elif provider == mlrun.
|
|
193
|
-
if mlrun.api.utils.singletons.k8s.
|
|
194
|
-
|
|
217
|
+
elif provider == mlrun.common.schemas.SecretProviderName.kubernetes:
|
|
218
|
+
if mlrun.api.utils.singletons.k8s.get_k8s_helper():
|
|
219
|
+
(
|
|
220
|
+
secret_name,
|
|
221
|
+
action,
|
|
222
|
+
) = mlrun.api.utils.singletons.k8s.get_k8s_helper().delete_project_secrets(
|
|
195
223
|
project, secrets
|
|
196
224
|
)
|
|
225
|
+
|
|
226
|
+
if action:
|
|
227
|
+
events_client = events_factory.EventsFactory().get_events_client()
|
|
228
|
+
event = events_client.generate_project_secret_event(
|
|
229
|
+
project=project,
|
|
230
|
+
secret_name=secret_name,
|
|
231
|
+
secret_keys=secrets,
|
|
232
|
+
action=action,
|
|
233
|
+
)
|
|
234
|
+
events_client.emit(event)
|
|
235
|
+
|
|
197
236
|
else:
|
|
198
237
|
raise mlrun.errors.MLRunInternalServerError(
|
|
199
238
|
"K8s provider cannot be initialized"
|
|
@@ -206,11 +245,11 @@ class Secrets(
|
|
|
206
245
|
def list_project_secret_keys(
|
|
207
246
|
self,
|
|
208
247
|
project: str,
|
|
209
|
-
provider: mlrun.
|
|
248
|
+
provider: mlrun.common.schemas.SecretProviderName,
|
|
210
249
|
token: typing.Optional[str] = None,
|
|
211
250
|
allow_internal_secrets: bool = False,
|
|
212
|
-
) -> mlrun.
|
|
213
|
-
if provider == mlrun.
|
|
251
|
+
) -> mlrun.common.schemas.SecretKeysData:
|
|
252
|
+
if provider == mlrun.common.schemas.SecretProviderName.vault:
|
|
214
253
|
if not token:
|
|
215
254
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
216
255
|
"Vault list project secret keys request without providing token"
|
|
@@ -219,15 +258,15 @@ class Secrets(
|
|
|
219
258
|
vault = mlrun.utils.vault.VaultStore(token)
|
|
220
259
|
secret_values = vault.get_secrets(None, project=project)
|
|
221
260
|
secret_keys = list(secret_values.keys())
|
|
222
|
-
elif provider == mlrun.
|
|
261
|
+
elif provider == mlrun.common.schemas.SecretProviderName.kubernetes:
|
|
223
262
|
if token:
|
|
224
263
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
225
264
|
"Cannot specify token when requesting k8s secret keys"
|
|
226
265
|
)
|
|
227
266
|
|
|
228
|
-
if mlrun.api.utils.singletons.k8s.
|
|
267
|
+
if mlrun.api.utils.singletons.k8s.get_k8s_helper():
|
|
229
268
|
secret_keys = (
|
|
230
|
-
mlrun.api.utils.singletons.k8s.
|
|
269
|
+
mlrun.api.utils.singletons.k8s.get_k8s_helper().get_project_secret_keys(
|
|
231
270
|
project
|
|
232
271
|
)
|
|
233
272
|
or []
|
|
@@ -248,20 +287,20 @@ class Secrets(
|
|
|
248
287
|
)
|
|
249
288
|
)
|
|
250
289
|
|
|
251
|
-
return mlrun.
|
|
290
|
+
return mlrun.common.schemas.SecretKeysData(
|
|
252
291
|
provider=provider, secret_keys=secret_keys
|
|
253
292
|
)
|
|
254
293
|
|
|
255
294
|
def list_project_secrets(
|
|
256
295
|
self,
|
|
257
296
|
project: str,
|
|
258
|
-
provider: mlrun.
|
|
297
|
+
provider: mlrun.common.schemas.SecretProviderName,
|
|
259
298
|
secrets: typing.Optional[typing.List[str]] = None,
|
|
260
299
|
token: typing.Optional[str] = None,
|
|
261
300
|
allow_secrets_from_k8s: bool = False,
|
|
262
301
|
allow_internal_secrets: bool = False,
|
|
263
|
-
) -> mlrun.
|
|
264
|
-
if provider == mlrun.
|
|
302
|
+
) -> mlrun.common.schemas.SecretsData:
|
|
303
|
+
if provider == mlrun.common.schemas.SecretProviderName.vault:
|
|
265
304
|
if not token:
|
|
266
305
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
267
306
|
"Vault list project secrets request without providing token"
|
|
@@ -269,13 +308,13 @@ class Secrets(
|
|
|
269
308
|
|
|
270
309
|
vault = mlrun.utils.vault.VaultStore(token)
|
|
271
310
|
secrets_data = vault.get_secrets(secrets, project=project)
|
|
272
|
-
elif provider == mlrun.
|
|
311
|
+
elif provider == mlrun.common.schemas.SecretProviderName.kubernetes:
|
|
273
312
|
if not allow_secrets_from_k8s:
|
|
274
313
|
raise mlrun.errors.MLRunAccessDeniedError(
|
|
275
314
|
"Not allowed to list secrets data from kubernetes provider"
|
|
276
315
|
)
|
|
277
316
|
secrets_data = (
|
|
278
|
-
mlrun.api.utils.singletons.k8s.
|
|
317
|
+
mlrun.api.utils.singletons.k8s.get_k8s_helper().get_project_secret_data(
|
|
279
318
|
project, secrets
|
|
280
319
|
)
|
|
281
320
|
)
|
|
@@ -290,12 +329,12 @@ class Secrets(
|
|
|
290
329
|
for key, value in secrets_data.items()
|
|
291
330
|
if not self._is_internal_project_secret_key(key)
|
|
292
331
|
}
|
|
293
|
-
return mlrun.
|
|
332
|
+
return mlrun.common.schemas.SecretsData(provider=provider, secrets=secrets_data)
|
|
294
333
|
|
|
295
334
|
def delete_project_secret(
|
|
296
335
|
self,
|
|
297
336
|
project: str,
|
|
298
|
-
provider: mlrun.
|
|
337
|
+
provider: mlrun.common.schemas.SecretProviderName,
|
|
299
338
|
secret_key: str,
|
|
300
339
|
token: typing.Optional[str] = None,
|
|
301
340
|
allow_secrets_from_k8s: bool = False,
|
|
@@ -321,7 +360,7 @@ class Secrets(
|
|
|
321
360
|
if key_map:
|
|
322
361
|
self.store_project_secrets(
|
|
323
362
|
project,
|
|
324
|
-
mlrun.
|
|
363
|
+
mlrun.common.schemas.SecretsData(
|
|
325
364
|
provider=provider,
|
|
326
365
|
secrets={key_map_secret_key: json.dumps(key_map)},
|
|
327
366
|
),
|
|
@@ -336,7 +375,7 @@ class Secrets(
|
|
|
336
375
|
def get_project_secret(
|
|
337
376
|
self,
|
|
338
377
|
project: str,
|
|
339
|
-
provider: mlrun.
|
|
378
|
+
provider: mlrun.common.schemas.SecretProviderName,
|
|
340
379
|
secret_key: str,
|
|
341
380
|
token: typing.Optional[str] = None,
|
|
342
381
|
allow_secrets_from_k8s: bool = False,
|
|
@@ -365,7 +404,7 @@ class Secrets(
|
|
|
365
404
|
def _resolve_project_secret_key(
|
|
366
405
|
self,
|
|
367
406
|
project: str,
|
|
368
|
-
provider: mlrun.
|
|
407
|
+
provider: mlrun.common.schemas.SecretProviderName,
|
|
369
408
|
secret_key: str,
|
|
370
409
|
token: typing.Optional[str] = None,
|
|
371
410
|
allow_secrets_from_k8s: bool = False,
|
|
@@ -373,7 +412,7 @@ class Secrets(
|
|
|
373
412
|
key_map_secret_key: typing.Optional[str] = None,
|
|
374
413
|
) -> typing.Tuple[bool, str]:
|
|
375
414
|
if key_map_secret_key:
|
|
376
|
-
if provider != mlrun.
|
|
415
|
+
if provider != mlrun.common.schemas.SecretProviderName.kubernetes:
|
|
377
416
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
378
417
|
f"Secret using key map is not implemented for provider {provider}"
|
|
379
418
|
)
|
|
@@ -395,7 +434,7 @@ class Secrets(
|
|
|
395
434
|
def _validate_and_enrich_project_secrets_to_store(
|
|
396
435
|
self,
|
|
397
436
|
project: str,
|
|
398
|
-
secrets: mlrun.
|
|
437
|
+
secrets: mlrun.common.schemas.SecretsData,
|
|
399
438
|
allow_internal_secrets: bool = False,
|
|
400
439
|
key_map_secret_key: typing.Optional[str] = None,
|
|
401
440
|
allow_storing_key_maps: bool = False,
|
|
@@ -418,7 +457,10 @@ class Secrets(
|
|
|
418
457
|
f"{self.key_map_secrets_key_prefix})"
|
|
419
458
|
)
|
|
420
459
|
if key_map_secret_key:
|
|
421
|
-
if
|
|
460
|
+
if (
|
|
461
|
+
secrets.provider
|
|
462
|
+
!= mlrun.common.schemas.SecretProviderName.kubernetes
|
|
463
|
+
):
|
|
422
464
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
423
465
|
f"Storing secret using key map is not implemented for provider {secrets.provider}"
|
|
424
466
|
)
|
|
@@ -466,7 +508,7 @@ class Secrets(
|
|
|
466
508
|
) -> typing.Optional[dict]:
|
|
467
509
|
secrets_data = self.list_project_secrets(
|
|
468
510
|
project,
|
|
469
|
-
mlrun.
|
|
511
|
+
mlrun.common.schemas.SecretProviderName.kubernetes,
|
|
470
512
|
[key_map_secret_key],
|
|
471
513
|
allow_secrets_from_k8s=True,
|
|
472
514
|
allow_internal_secrets=True,
|
mlrun/api/crud/tags.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.
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
import sqlalchemy.orm
|
|
16
16
|
|
|
17
17
|
import mlrun.api.db.sqldb.db
|
|
18
|
-
import mlrun.api.schemas
|
|
19
18
|
import mlrun.api.utils.projects.remotes.follower
|
|
20
19
|
import mlrun.api.utils.singletons.db
|
|
21
20
|
import mlrun.api.utils.singletons.project_member
|
|
21
|
+
import mlrun.common.schemas
|
|
22
22
|
import mlrun.config
|
|
23
23
|
import mlrun.errors
|
|
24
24
|
import mlrun.utils.singleton
|
|
@@ -40,7 +40,7 @@ class Tags(
|
|
|
40
40
|
db_session: sqlalchemy.orm.Session,
|
|
41
41
|
project: str,
|
|
42
42
|
tag: str,
|
|
43
|
-
tag_objects: mlrun.
|
|
43
|
+
tag_objects: mlrun.common.schemas.TagObjects,
|
|
44
44
|
):
|
|
45
45
|
overwrite_func = kind_to_function_names.get(tag_objects.kind, {}).get(
|
|
46
46
|
"overwrite"
|
|
@@ -61,7 +61,7 @@ class Tags(
|
|
|
61
61
|
db_session: sqlalchemy.orm.Session,
|
|
62
62
|
project: str,
|
|
63
63
|
tag: str,
|
|
64
|
-
tag_objects: mlrun.
|
|
64
|
+
tag_objects: mlrun.common.schemas.TagObjects,
|
|
65
65
|
):
|
|
66
66
|
append_func = kind_to_function_names.get(tag_objects.kind, {}).get("append")
|
|
67
67
|
if not append_func:
|
|
@@ -80,7 +80,7 @@ class Tags(
|
|
|
80
80
|
db_session: sqlalchemy.orm.Session,
|
|
81
81
|
project: str,
|
|
82
82
|
tag: str,
|
|
83
|
-
tag_objects: mlrun.
|
|
83
|
+
tag_objects: mlrun.common.schemas.TagObjects,
|
|
84
84
|
):
|
|
85
85
|
delete_func = kind_to_function_names.get(tag_objects.kind, {}).get("delete")
|
|
86
86
|
if not delete_func:
|