mlrun 1.5.0rc1__py3-none-any.whl → 1.5.0rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mlrun might be problematic. Click here for more details.

Files changed (119) hide show
  1. mlrun/__init__.py +2 -35
  2. mlrun/__main__.py +1 -40
  3. mlrun/api/api/api.py +6 -0
  4. mlrun/api/api/endpoints/feature_store.py +0 -4
  5. mlrun/api/api/endpoints/files.py +14 -2
  6. mlrun/api/api/endpoints/functions.py +6 -1
  7. mlrun/api/api/endpoints/logs.py +17 -3
  8. mlrun/api/api/endpoints/pipelines.py +1 -5
  9. mlrun/api/api/endpoints/projects.py +88 -0
  10. mlrun/api/api/endpoints/runs.py +48 -6
  11. mlrun/api/api/endpoints/workflows.py +355 -0
  12. mlrun/api/api/utils.py +1 -1
  13. mlrun/api/crud/__init__.py +1 -0
  14. mlrun/api/crud/client_spec.py +3 -0
  15. mlrun/api/crud/model_monitoring/deployment.py +36 -7
  16. mlrun/api/crud/model_monitoring/grafana.py +1 -1
  17. mlrun/api/crud/model_monitoring/helpers.py +32 -2
  18. mlrun/api/crud/model_monitoring/model_endpoints.py +27 -5
  19. mlrun/api/crud/notifications.py +9 -4
  20. mlrun/api/crud/pipelines.py +4 -9
  21. mlrun/api/crud/runtime_resources.py +4 -3
  22. mlrun/api/crud/secrets.py +21 -0
  23. mlrun/api/crud/workflows.py +352 -0
  24. mlrun/api/db/base.py +16 -1
  25. mlrun/api/db/sqldb/db.py +97 -16
  26. mlrun/api/launcher.py +26 -7
  27. mlrun/api/main.py +3 -4
  28. mlrun/{mlutils → api/rundb}/__init__.py +2 -6
  29. mlrun/{db → api/rundb}/sqldb.py +35 -83
  30. mlrun/api/runtime_handlers/__init__.py +56 -0
  31. mlrun/api/runtime_handlers/base.py +1247 -0
  32. mlrun/api/runtime_handlers/daskjob.py +209 -0
  33. mlrun/api/runtime_handlers/kubejob.py +37 -0
  34. mlrun/api/runtime_handlers/mpijob.py +147 -0
  35. mlrun/api/runtime_handlers/remotesparkjob.py +29 -0
  36. mlrun/api/runtime_handlers/sparkjob.py +148 -0
  37. mlrun/api/utils/builder.py +1 -4
  38. mlrun/api/utils/clients/chief.py +14 -0
  39. mlrun/api/utils/scheduler.py +98 -15
  40. mlrun/api/utils/singletons/db.py +4 -0
  41. mlrun/artifacts/manager.py +1 -2
  42. mlrun/common/schemas/__init__.py +6 -0
  43. mlrun/common/schemas/auth.py +4 -1
  44. mlrun/common/schemas/client_spec.py +1 -1
  45. mlrun/common/schemas/model_monitoring/__init__.py +1 -0
  46. mlrun/common/schemas/model_monitoring/constants.py +11 -0
  47. mlrun/common/schemas/project.py +1 -0
  48. mlrun/common/schemas/runs.py +1 -8
  49. mlrun/common/schemas/schedule.py +1 -8
  50. mlrun/common/schemas/workflow.py +54 -0
  51. mlrun/config.py +42 -40
  52. mlrun/datastore/sources.py +1 -1
  53. mlrun/db/__init__.py +4 -68
  54. mlrun/db/base.py +12 -0
  55. mlrun/db/factory.py +65 -0
  56. mlrun/db/httpdb.py +175 -19
  57. mlrun/db/nopdb.py +4 -2
  58. mlrun/execution.py +4 -2
  59. mlrun/feature_store/__init__.py +1 -0
  60. mlrun/feature_store/api.py +1 -2
  61. mlrun/feature_store/feature_set.py +0 -10
  62. mlrun/feature_store/feature_vector.py +340 -2
  63. mlrun/feature_store/ingestion.py +5 -10
  64. mlrun/feature_store/retrieval/base.py +118 -104
  65. mlrun/feature_store/retrieval/dask_merger.py +17 -10
  66. mlrun/feature_store/retrieval/job.py +4 -1
  67. mlrun/feature_store/retrieval/local_merger.py +18 -18
  68. mlrun/feature_store/retrieval/spark_merger.py +21 -14
  69. mlrun/feature_store/retrieval/storey_merger.py +21 -15
  70. mlrun/kfpops.py +3 -9
  71. mlrun/launcher/base.py +3 -3
  72. mlrun/launcher/client.py +3 -2
  73. mlrun/launcher/factory.py +16 -13
  74. mlrun/lists.py +0 -11
  75. mlrun/model.py +9 -15
  76. mlrun/model_monitoring/helpers.py +15 -25
  77. mlrun/model_monitoring/model_monitoring_batch.py +72 -4
  78. mlrun/model_monitoring/prometheus.py +219 -0
  79. mlrun/model_monitoring/stores/__init__.py +15 -9
  80. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +3 -1
  81. mlrun/model_monitoring/stream_processing.py +181 -29
  82. mlrun/package/packager.py +6 -8
  83. mlrun/package/packagers/default_packager.py +121 -10
  84. mlrun/platforms/__init__.py +0 -2
  85. mlrun/platforms/iguazio.py +0 -56
  86. mlrun/projects/pipelines.py +57 -158
  87. mlrun/projects/project.py +6 -32
  88. mlrun/render.py +1 -1
  89. mlrun/run.py +2 -124
  90. mlrun/runtimes/__init__.py +6 -42
  91. mlrun/runtimes/base.py +26 -1241
  92. mlrun/runtimes/daskjob.py +2 -198
  93. mlrun/runtimes/function.py +16 -5
  94. mlrun/runtimes/kubejob.py +5 -29
  95. mlrun/runtimes/mpijob/__init__.py +2 -2
  96. mlrun/runtimes/mpijob/abstract.py +10 -1
  97. mlrun/runtimes/mpijob/v1.py +0 -76
  98. mlrun/runtimes/mpijob/v1alpha1.py +1 -74
  99. mlrun/runtimes/nuclio.py +3 -2
  100. mlrun/runtimes/pod.py +0 -10
  101. mlrun/runtimes/remotesparkjob.py +1 -15
  102. mlrun/runtimes/serving.py +1 -1
  103. mlrun/runtimes/sparkjob/__init__.py +0 -1
  104. mlrun/runtimes/sparkjob/abstract.py +4 -131
  105. mlrun/serving/states.py +1 -1
  106. mlrun/utils/db.py +0 -2
  107. mlrun/utils/helpers.py +19 -13
  108. mlrun/utils/notifications/notification_pusher.py +5 -25
  109. mlrun/utils/regex.py +7 -2
  110. mlrun/utils/version/version.json +2 -2
  111. {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/METADATA +24 -23
  112. {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/RECORD +116 -107
  113. {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/WHEEL +1 -1
  114. mlrun/mlutils/data.py +0 -160
  115. mlrun/mlutils/models.py +0 -78
  116. mlrun/mlutils/plots.py +0 -902
  117. {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/LICENSE +0 -0
  118. {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/entry_points.txt +0 -0
  119. {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/top_level.txt +0 -0
mlrun/__init__.py CHANGED
@@ -36,14 +36,7 @@ from .errors import MLRunInvalidArgumentError, MLRunNotFoundError
36
36
  from .execution import MLClientCtx
37
37
  from .model import RunObject, RunTemplate, new_task
38
38
  from .package import ArtifactType, DefaultPackager, Packager, handler
39
- from .platforms import (
40
- VolumeMount,
41
- auto_mount,
42
- mount_v3io,
43
- mount_v3io_extended,
44
- mount_v3io_legacy,
45
- v3io_cred,
46
- )
39
+ from .platforms import VolumeMount, auto_mount, mount_v3io, v3io_cred
47
40
  from .projects import (
48
41
  ProjectMetadata,
49
42
  build_function,
@@ -66,7 +59,6 @@ from .run import (
66
59
  import_function,
67
60
  new_function,
68
61
  run_local,
69
- run_pipeline,
70
62
  wait_for_pipeline_completion,
71
63
  )
72
64
  from .runtimes import new_model_server
@@ -91,9 +83,7 @@ if "IGZ_NAMESPACE_DOMAIN" in environ:
91
83
  def set_environment(
92
84
  api_path: str = None,
93
85
  artifact_path: str = "",
94
- project: str = "",
95
86
  access_key: str = None,
96
- user_project=False,
97
87
  username: str = None,
98
88
  env_file: str = None,
99
89
  mock_functions: str = None,
@@ -109,18 +99,14 @@ def set_environment(
109
99
  example::
110
100
 
111
101
  from os import path
112
- project_name, artifact_path = set_environment(project='my-project')
102
+ project_name, artifact_path = set_environment()
113
103
  set_environment("http://localhost:8080", artifact_path="./")
114
104
  set_environment(env_file="mlrun.env")
115
105
  set_environment("<remote-service-url>", access_key="xyz", username="joe")
116
106
 
117
107
  :param api_path: location/url of mlrun api service
118
108
  :param artifact_path: path/url for storing experiment artifacts
119
- :param project: default project name (deprecated in 1.3.0 and will be removed in 1.5.0) - use project
120
- APIs such as `get_or_create_project`, `load_project` to configure the active project
121
109
  :param access_key: set the remote cluster access key (V3IO_ACCESS_KEY)
122
- :param user_project: add the current user name to the provided project name (making it unique per user)
123
- (deprecated in 1.3.0 and will be removed in 1.5.0)
124
110
  :param username: name of the user to authenticate
125
111
  :param env_file: path/url to .env file (holding MLRun config and other env vars), see: set_env_from_file()
126
112
  :param mock_functions: set to True to create local/mock functions instead of real containers,
@@ -129,14 +115,6 @@ def set_environment(
129
115
  default project name
130
116
  actual artifact path/url, can be used to create subpaths per task or group of artifacts
131
117
  """
132
- if user_project or project:
133
- warnings.warn(
134
- "'user_project' and 'project' are deprecated in 1.3.0, and will be removed in 1.5.0, use project "
135
- "APIs such as 'get_or_create_project', 'load_project' to configure the active project.",
136
- # TODO: Remove in 1.5.0
137
- FutureWarning,
138
- )
139
-
140
118
  if env_file:
141
119
  set_env_from_file(env_file)
142
120
 
@@ -160,17 +138,6 @@ def set_environment(
160
138
  if api_path:
161
139
  environ["MLRUN_DBPATH"] = mlconf.dbpath
162
140
 
163
- project = _add_username_to_project_name_if_needed(project, user_project)
164
- if project:
165
- ProjectMetadata.validate_project_name(project)
166
-
167
- mlconf.default_project = project or mlconf.default_project
168
- # We want to ensure the project exists, and verify we're authorized to work on it
169
- # if it doesn't exist this will create it (and obviously if we created it, we're authorized to work on it)
170
- # if it does exist - this will get it, which will fail if we're not authorized to work on it
171
- if project:
172
- get_or_create_project(mlconf.default_project, "./")
173
-
174
141
  if not mlconf.artifact_path and not artifact_path:
175
142
  raise ValueError(
176
143
  "default artifact_path was not configured, please specify a valid artifact_path"
mlrun/__main__.py CHANGED
@@ -17,7 +17,6 @@ import json
17
17
  import pathlib
18
18
  import socket
19
19
  import traceback
20
- import warnings
21
20
  from ast import literal_eval
22
21
  from base64 import b64decode, b64encode
23
22
  from os import environ, path, remove
@@ -592,12 +591,6 @@ def build(
592
591
  default="",
593
592
  help="path/url of function yaml or function " "yaml or db://<project>/<name>[:tag]",
594
593
  )
595
- @click.option(
596
- "--dashboard",
597
- "-d",
598
- default="",
599
- help="Deprecated. Keep empty to allow auto-detect by MLRun API",
600
- )
601
594
  @click.option("--project", "-p", default="", help="project name")
602
595
  @click.option("--model", "-m", multiple=True, help="model name and path (name=path)")
603
596
  @click.option("--kind", "-k", default=None, help="runtime sub kind")
@@ -616,7 +609,6 @@ def deploy(
616
609
  spec,
617
610
  source,
618
611
  func_url,
619
- dashboard,
620
612
  project,
621
613
  model,
622
614
  tag,
@@ -677,16 +669,8 @@ def deploy(
677
669
  function.set_env(k, v)
678
670
  function.verbose = verbose
679
671
 
680
- if dashboard:
681
- warnings.warn(
682
- "'--dashboard' is deprecated in 1.3.0, and will be removed in 1.5.0, "
683
- "Keep '--dashboard' value empty to allow auto-detection by MLRun API.",
684
- # TODO: Remove in 1.5.0
685
- FutureWarning,
686
- )
687
-
688
672
  try:
689
- addr = function.deploy(dashboard=dashboard, project=project, tag=tag)
673
+ addr = function.deploy(project=project, tag=tag)
690
674
  except Exception as err:
691
675
  print(f"deploy error: {err_to_str(err)}")
692
676
  exit(1)
@@ -1005,12 +989,6 @@ def logs(uid, project, offset, db, watch):
1005
989
  @click.option(
1006
990
  "--env-file", default="", help="path to .env file to load config/variables from"
1007
991
  )
1008
- # TODO: Remove --ensure-project in 1.5.0
1009
- @click.option(
1010
- "--ensure-project",
1011
- is_flag=True,
1012
- help="ensure the project exists, if not, create project",
1013
- )
1014
992
  @click.option(
1015
993
  "--save/--no-save",
1016
994
  default=True,
@@ -1025,13 +1003,6 @@ def logs(uid, project, offset, db, watch):
1025
1003
  "https://apscheduler.readthedocs.io/en/3.x/modules/triggers/cron.html#module-apscheduler.triggers.cron."
1026
1004
  "For using the pre-defined workflow's schedule, set --schedule 'true'",
1027
1005
  )
1028
- # TODO: Remove in 1.5.0
1029
- @click.option(
1030
- "--overwrite-schedule",
1031
- "-os",
1032
- is_flag=True,
1033
- help="Overwrite a schedule when submitting a new one with the same name.",
1034
- )
1035
1006
  @click.option(
1036
1007
  "--save-secrets",
1037
1008
  is_flag=True,
@@ -1069,10 +1040,8 @@ def project(
1069
1040
  local,
1070
1041
  env_file,
1071
1042
  timeout,
1072
- ensure_project,
1073
1043
  schedule,
1074
1044
  notifications,
1075
- overwrite_schedule,
1076
1045
  save_secrets,
1077
1046
  save,
1078
1047
  ):
@@ -1080,13 +1049,6 @@ def project(
1080
1049
  if env_file:
1081
1050
  mlrun.set_env_from_file(env_file)
1082
1051
 
1083
- if ensure_project:
1084
- warnings.warn(
1085
- "'ensure_project' is deprecated and will be removed in 1.5.0, use 'save' (True by default) instead. ",
1086
- # TODO: Remove this in 1.5.0
1087
- FutureWarning,
1088
- )
1089
-
1090
1052
  if db:
1091
1053
  mlconf.dbpath = db
1092
1054
 
@@ -1169,7 +1131,6 @@ def project(
1169
1131
  local=local,
1170
1132
  schedule=schedule,
1171
1133
  timeout=timeout,
1172
- overwrite=overwrite_schedule,
1173
1134
  )
1174
1135
  except Exception as err:
1175
1136
  print(traceback.format_exc())
mlrun/api/api/api.py CHANGED
@@ -41,6 +41,7 @@ from mlrun.api.api.endpoints import (
41
41
  secrets,
42
42
  submit,
43
43
  tags,
44
+ workflows,
44
45
  )
45
46
 
46
47
  api_router = APIRouter(dependencies=[Depends(mlrun.api.api.deps.verify_api_state)])
@@ -145,3 +146,8 @@ api_router.include_router(
145
146
  tags=["internal"],
146
147
  dependencies=[Depends(mlrun.api.api.deps.authenticate_request)],
147
148
  )
149
+ api_router.include_router(
150
+ workflows.router,
151
+ tags=["workflows"],
152
+ dependencies=[Depends(mlrun.api.api.deps.authenticate_request)],
153
+ )
@@ -408,10 +408,6 @@ async def ingest_feature_set(
408
408
  mlrun.common.schemas.AuthorizationAction.read,
409
409
  auth_info,
410
410
  )
411
- # Need to override the default rundb since we're in the server.
412
- # this is done so further down the flow when running the function created for ingestion we won't access the httpdb
413
- # but rather "understand" that we are running on server side and call the DB.
414
- await run_in_threadpool(feature_set._override_run_db, db_session)
415
411
 
416
412
  if ingest_parameters.targets:
417
413
  data_targets = [
@@ -31,7 +31,13 @@ from mlrun.utils import logger
31
31
  router = fastapi.APIRouter()
32
32
 
33
33
 
34
- @router.get("/files")
34
+ # TODO: Remove in 1.7.0
35
+ @router.get(
36
+ "/files",
37
+ deprecated=True,
38
+ description="'/files' and '/filestat' will be removed in 1.7.0, "
39
+ "use /projects/{project}/files instead.",
40
+ )
35
41
  def get_files(
36
42
  schema: str = "",
37
43
  objpath: str = fastapi.Query("", alias="path"),
@@ -73,7 +79,13 @@ async def get_files_with_project_secrets(
73
79
  )
74
80
 
75
81
 
76
- @router.get("/filestat")
82
+ # TODO: Remove in 1.7.0
83
+ @router.get(
84
+ "/filestat",
85
+ deprecated=True,
86
+ description="'/files' and '/filestat' will be removed in 1.7.0, "
87
+ "use /projects/{project}/filestat instead.",
88
+ )
77
89
  def get_filestat(
78
90
  schema: str = "",
79
91
  path: str = "",
@@ -706,9 +706,14 @@ def _build_function(
706
706
  reason=f"runtime error: {err_to_str(err)}",
707
707
  )
708
708
  try:
709
+ # connect to run db
709
710
  run_db = get_run_db_instance(db_session)
710
711
  fn.set_db_connection(run_db)
711
- mlrun.api.launcher.ServerSideLauncher.enrich_runtime(runtime=fn)
712
+
713
+ # enrich runtime with project defaults
714
+ launcher = mlrun.api.launcher.ServerSideLauncher()
715
+ launcher.enrich_runtime(runtime=fn)
716
+
712
717
  fn.save(versioned=False)
713
718
  if fn.kind in RuntimeKinds.nuclio_runtimes():
714
719
  mlrun.api.api.utils.apply_enrichment_and_validation_on_function(
@@ -21,10 +21,17 @@ import mlrun.api.crud
21
21
  import mlrun.api.utils.auth.verifier
22
22
  import mlrun.common.schemas
23
23
 
24
- router = fastapi.APIRouter(prefix="/log/{project}")
24
+ router = fastapi.APIRouter()
25
25
 
26
26
 
27
- @router.post("/{uid}")
27
+ # TODO: remove /log/{project}/{uid} in 1.7.0
28
+ @router.post(
29
+ "/log/{project}/{uid}",
30
+ deprecated=True,
31
+ description="/log/{project}/{uid} is deprecated in 1.5.0 and will be removed in 1.7.0, "
32
+ "use /projects/{project}/logs/{uid} instead",
33
+ )
34
+ @router.post("/projects/{project}/logs/{uid}")
28
35
  async def store_log(
29
36
  request: fastapi.Request,
30
37
  project: str,
@@ -52,7 +59,14 @@ async def store_log(
52
59
  return {}
53
60
 
54
61
 
55
- @router.get("/{uid}")
62
+ # TODO: remove /log/{project}/{uid} in 1.7.0
63
+ @router.get(
64
+ "/log/{project}/{uid}",
65
+ deprecated=True,
66
+ description="/log/{project}/{uid} is deprecated in 1.5.0 and will be removed in 1.7.0, "
67
+ "use /projects/{project}/logs/{uid} instead",
68
+ )
69
+ @router.get("/projects/{project}/logs/{uid}")
56
70
  async def get_log(
57
71
  project: str,
58
72
  uid: str,
@@ -129,11 +129,9 @@ async def get_pipeline(
129
129
  auth_info: mlrun.common.schemas.AuthInfo = Depends(
130
130
  mlrun.api.api.deps.authenticate_request
131
131
  ),
132
- db_session: Session = Depends(deps.get_db_session),
133
132
  ):
134
133
  pipeline = await run_in_threadpool(
135
134
  mlrun.api.crud.Pipelines().get_pipeline,
136
- db_session,
137
135
  run_id,
138
136
  project,
139
137
  namespace,
@@ -145,7 +143,7 @@ async def get_pipeline(
145
143
  # legacy flow in which we first get the pipeline, resolve the project out of it, and only then query permissions
146
144
  # we don't use the return value from this function since the user may have asked for a different format than
147
145
  # summary which is the one used inside
148
- await _get_pipeline_without_project(db_session, auth_info, run_id, namespace)
146
+ await _get_pipeline_without_project(auth_info, run_id, namespace)
149
147
  else:
150
148
  await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_resource_permissions(
151
149
  mlrun.common.schemas.AuthorizationResourceTypes.pipeline,
@@ -158,7 +156,6 @@ async def get_pipeline(
158
156
 
159
157
 
160
158
  async def _get_pipeline_without_project(
161
- db_session: Session,
162
159
  auth_info: mlrun.common.schemas.AuthInfo,
163
160
  run_id: str,
164
161
  namespace: str,
@@ -170,7 +167,6 @@ async def _get_pipeline_without_project(
170
167
  """
171
168
  run = await run_in_threadpool(
172
169
  mlrun.api.crud.Pipelines().get_pipeline,
173
- db_session,
174
170
  run_id,
175
171
  namespace=namespace,
176
172
  # minimal format that includes the project
@@ -20,6 +20,7 @@ import sqlalchemy.orm
20
20
  from fastapi.concurrency import run_in_threadpool
21
21
 
22
22
  import mlrun.api.api.deps
23
+ import mlrun.api.crud
23
24
  import mlrun.api.utils.auth.verifier
24
25
  import mlrun.api.utils.clients.chief
25
26
  import mlrun.common.schemas
@@ -323,6 +324,93 @@ async def get_project_summary(
323
324
  return project_summary
324
325
 
325
326
 
327
+ @router.post("/projects/{name}/load")
328
+ async def load_project(
329
+ name: str,
330
+ url: str,
331
+ secrets: mlrun.common.schemas.SecretsData = None,
332
+ auth_info: mlrun.common.schemas.AuthInfo = fastapi.Depends(
333
+ mlrun.api.api.deps.authenticate_request
334
+ ),
335
+ db_session: sqlalchemy.orm.Session = fastapi.Depends(
336
+ mlrun.api.api.deps.get_db_session
337
+ ),
338
+ ):
339
+ """
340
+ Loading a project remotely from a given source.
341
+
342
+ :param name: project name
343
+ :param url: git or tar.gz or .zip sources archive path e.g.:
344
+ git://github.com/mlrun/demo-xgb-project.git
345
+ http://mysite/archived-project.zip
346
+ The git project should include the project yaml file.
347
+ :param secrets: Secrets to store in project in order to load it from the provided url.
348
+ For more information see :py:func:`mlrun.load_project` function.
349
+ :param auth_info: auth info of the request
350
+ :param db_session: session that manages the current dialog with the database
351
+
352
+ :returns: a Run object of the load project function
353
+ """
354
+
355
+ project = mlrun.common.schemas.Project(
356
+ metadata=mlrun.common.schemas.ProjectMetadata(name=name),
357
+ spec=mlrun.common.schemas.ProjectSpec(source=url),
358
+ )
359
+
360
+ # We must create the project before we run the remote load_project function because
361
+ # we want this function will be running under the project itself instead of the default project.
362
+ project, _ = await fastapi.concurrency.run_in_threadpool(
363
+ get_project_member().create_project,
364
+ db_session=db_session,
365
+ project=project,
366
+ projects_role=auth_info.projects_role,
367
+ leader_session=auth_info.session,
368
+ )
369
+
370
+ # Storing secrets in project
371
+ if secrets is not None:
372
+ await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_resource_permissions(
373
+ mlrun.common.schemas.AuthorizationResourceTypes.secret,
374
+ project.metadata.name,
375
+ secrets.provider,
376
+ mlrun.common.schemas.AuthorizationAction.create,
377
+ auth_info,
378
+ )
379
+
380
+ await run_in_threadpool(
381
+ mlrun.api.crud.Secrets().store_project_secrets,
382
+ project.metadata.name,
383
+ secrets,
384
+ )
385
+
386
+ # Creating the auxiliary function for loading the project:
387
+ load_project_runner = await fastapi.concurrency.run_in_threadpool(
388
+ mlrun.api.crud.WorkflowRunners().create_runner,
389
+ run_name=f"load-{name}",
390
+ project=name,
391
+ db_session=db_session,
392
+ auth_info=auth_info,
393
+ image=mlrun.mlconf.default_base_image,
394
+ )
395
+
396
+ logger.debug(
397
+ "Saved function for loading project",
398
+ project_name=name,
399
+ function_name=load_project_runner.metadata.name,
400
+ kind=load_project_runner.kind,
401
+ source=project.spec.source,
402
+ )
403
+
404
+ run = await fastapi.concurrency.run_in_threadpool(
405
+ mlrun.api.crud.WorkflowRunners().run,
406
+ runner=load_project_runner,
407
+ project=project,
408
+ workflow_request=None,
409
+ load_only=True,
410
+ )
411
+ return {"data": run.to_dict()}
412
+
413
+
326
414
  def _is_request_from_leader(
327
415
  projects_role: typing.Optional[mlrun.common.schemas.ProjectsRole],
328
416
  ) -> bool:
@@ -31,7 +31,14 @@ from mlrun.utils.helpers import datetime_from_iso
31
31
  router = APIRouter()
32
32
 
33
33
 
34
- @router.post("/run/{project}/{uid}")
34
+ # TODO: remove /run/{project}/{uid} in 1.7.0
35
+ @router.post(
36
+ "/run/{project}/{uid}",
37
+ deprecated=True,
38
+ description="/run/{project}/{uid} is deprecated in 1.5.0 and will be removed in 1.7.0, "
39
+ "use /projects/{project}/runs/{uid} instead",
40
+ )
41
+ @router.post("/projects/{project}/runs/{uid}")
35
42
  async def store_run(
36
43
  request: Request,
37
44
  project: str,
@@ -70,7 +77,14 @@ async def store_run(
70
77
  return {}
71
78
 
72
79
 
73
- @router.patch("/run/{project}/{uid}")
80
+ # TODO: remove /run/{project}/{uid} in 1.7.0
81
+ @router.patch(
82
+ "/run/{project}/{uid}",
83
+ deprecated=True,
84
+ description="/run/{project}/{uid} is deprecated in 1.5.0 and will be removed in 1.7.0, "
85
+ "use /projects/{project}/runs/{uid} instead",
86
+ )
87
+ @router.patch("/projects/{project}/runs/{uid}")
74
88
  async def update_run(
75
89
  request: Request,
76
90
  project: str,
@@ -103,7 +117,14 @@ async def update_run(
103
117
  return {}
104
118
 
105
119
 
106
- @router.get("/run/{project}/{uid}")
120
+ # TODO: remove /run/{project}/{uid} in 1.7.0
121
+ @router.get(
122
+ "/run/{project}/{uid}",
123
+ deprecated=True,
124
+ description="/run/{project}/{uid} is deprecated in 1.5.0 and will be removed in 1.7.0, "
125
+ "use /projects/{project}/runs/{uid} instead",
126
+ )
127
+ @router.get("/projects/{project}/runs/{uid}")
107
128
  async def get_run(
108
129
  project: str,
109
130
  uid: str,
@@ -126,7 +147,14 @@ async def get_run(
126
147
  }
127
148
 
128
149
 
129
- @router.delete("/run/{project}/{uid}")
150
+ # TODO: remove /run/{project}/{uid} in 1.7.0
151
+ @router.delete(
152
+ "/run/{project}/{uid}",
153
+ deprecated=True,
154
+ description="/run/{project}/{uid} is deprecated in 1.5.0 and will be removed in 1.7.0, "
155
+ "use /projects/{project}/runs/{uid} instead",
156
+ )
157
+ @router.delete("/projects/{project}/runs/{uid}")
130
158
  async def delete_run(
131
159
  project: str,
132
160
  uid: str,
@@ -151,7 +179,14 @@ async def delete_run(
151
179
  return {}
152
180
 
153
181
 
154
- @router.get("/runs")
182
+ # TODO: remove /runs in 1.7.0
183
+ @router.get(
184
+ "/runs",
185
+ deprecated=True,
186
+ description="/runs is deprecated in 1.5.0 and will be removed in 1.7.0, "
187
+ "use /projects/{project}/runs/{uid} instead",
188
+ )
189
+ @router.get("/projects/{project}/runs")
155
190
  async def list_runs(
156
191
  project: str = None,
157
192
  name: str = None,
@@ -222,7 +257,14 @@ async def list_runs(
222
257
  }
223
258
 
224
259
 
225
- @router.delete("/runs")
260
+ # TODO: remove /runs in 1.7.0
261
+ @router.delete(
262
+ "/runs",
263
+ deprecated=True,
264
+ description="/runs is deprecated in 1.5.0 and will be removed in 1.7.0, "
265
+ "use /projects/{project}/runs/{uid} instead",
266
+ )
267
+ @router.delete("/projects/{project}/runs")
226
268
  async def delete_runs(
227
269
  project: str = None,
228
270
  name: str = None,