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.
- mlrun/__init__.py +2 -35
- mlrun/__main__.py +1 -40
- mlrun/api/api/api.py +6 -0
- mlrun/api/api/endpoints/feature_store.py +0 -4
- mlrun/api/api/endpoints/files.py +14 -2
- mlrun/api/api/endpoints/functions.py +6 -1
- mlrun/api/api/endpoints/logs.py +17 -3
- mlrun/api/api/endpoints/pipelines.py +1 -5
- mlrun/api/api/endpoints/projects.py +88 -0
- mlrun/api/api/endpoints/runs.py +48 -6
- mlrun/api/api/endpoints/workflows.py +355 -0
- mlrun/api/api/utils.py +1 -1
- mlrun/api/crud/__init__.py +1 -0
- mlrun/api/crud/client_spec.py +3 -0
- mlrun/api/crud/model_monitoring/deployment.py +36 -7
- mlrun/api/crud/model_monitoring/grafana.py +1 -1
- mlrun/api/crud/model_monitoring/helpers.py +32 -2
- mlrun/api/crud/model_monitoring/model_endpoints.py +27 -5
- mlrun/api/crud/notifications.py +9 -4
- mlrun/api/crud/pipelines.py +4 -9
- mlrun/api/crud/runtime_resources.py +4 -3
- mlrun/api/crud/secrets.py +21 -0
- mlrun/api/crud/workflows.py +352 -0
- mlrun/api/db/base.py +16 -1
- mlrun/api/db/sqldb/db.py +97 -16
- mlrun/api/launcher.py +26 -7
- mlrun/api/main.py +3 -4
- mlrun/{mlutils → api/rundb}/__init__.py +2 -6
- mlrun/{db → api/rundb}/sqldb.py +35 -83
- mlrun/api/runtime_handlers/__init__.py +56 -0
- mlrun/api/runtime_handlers/base.py +1247 -0
- mlrun/api/runtime_handlers/daskjob.py +209 -0
- mlrun/api/runtime_handlers/kubejob.py +37 -0
- mlrun/api/runtime_handlers/mpijob.py +147 -0
- mlrun/api/runtime_handlers/remotesparkjob.py +29 -0
- mlrun/api/runtime_handlers/sparkjob.py +148 -0
- mlrun/api/utils/builder.py +1 -4
- mlrun/api/utils/clients/chief.py +14 -0
- mlrun/api/utils/scheduler.py +98 -15
- mlrun/api/utils/singletons/db.py +4 -0
- mlrun/artifacts/manager.py +1 -2
- mlrun/common/schemas/__init__.py +6 -0
- mlrun/common/schemas/auth.py +4 -1
- mlrun/common/schemas/client_spec.py +1 -1
- mlrun/common/schemas/model_monitoring/__init__.py +1 -0
- mlrun/common/schemas/model_monitoring/constants.py +11 -0
- mlrun/common/schemas/project.py +1 -0
- mlrun/common/schemas/runs.py +1 -8
- mlrun/common/schemas/schedule.py +1 -8
- mlrun/common/schemas/workflow.py +54 -0
- mlrun/config.py +42 -40
- mlrun/datastore/sources.py +1 -1
- mlrun/db/__init__.py +4 -68
- mlrun/db/base.py +12 -0
- mlrun/db/factory.py +65 -0
- mlrun/db/httpdb.py +175 -19
- mlrun/db/nopdb.py +4 -2
- mlrun/execution.py +4 -2
- mlrun/feature_store/__init__.py +1 -0
- mlrun/feature_store/api.py +1 -2
- mlrun/feature_store/feature_set.py +0 -10
- mlrun/feature_store/feature_vector.py +340 -2
- mlrun/feature_store/ingestion.py +5 -10
- mlrun/feature_store/retrieval/base.py +118 -104
- mlrun/feature_store/retrieval/dask_merger.py +17 -10
- mlrun/feature_store/retrieval/job.py +4 -1
- mlrun/feature_store/retrieval/local_merger.py +18 -18
- mlrun/feature_store/retrieval/spark_merger.py +21 -14
- mlrun/feature_store/retrieval/storey_merger.py +21 -15
- mlrun/kfpops.py +3 -9
- mlrun/launcher/base.py +3 -3
- mlrun/launcher/client.py +3 -2
- mlrun/launcher/factory.py +16 -13
- mlrun/lists.py +0 -11
- mlrun/model.py +9 -15
- mlrun/model_monitoring/helpers.py +15 -25
- mlrun/model_monitoring/model_monitoring_batch.py +72 -4
- mlrun/model_monitoring/prometheus.py +219 -0
- mlrun/model_monitoring/stores/__init__.py +15 -9
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +3 -1
- mlrun/model_monitoring/stream_processing.py +181 -29
- mlrun/package/packager.py +6 -8
- mlrun/package/packagers/default_packager.py +121 -10
- mlrun/platforms/__init__.py +0 -2
- mlrun/platforms/iguazio.py +0 -56
- mlrun/projects/pipelines.py +57 -158
- mlrun/projects/project.py +6 -32
- mlrun/render.py +1 -1
- mlrun/run.py +2 -124
- mlrun/runtimes/__init__.py +6 -42
- mlrun/runtimes/base.py +26 -1241
- mlrun/runtimes/daskjob.py +2 -198
- mlrun/runtimes/function.py +16 -5
- mlrun/runtimes/kubejob.py +5 -29
- mlrun/runtimes/mpijob/__init__.py +2 -2
- mlrun/runtimes/mpijob/abstract.py +10 -1
- mlrun/runtimes/mpijob/v1.py +0 -76
- mlrun/runtimes/mpijob/v1alpha1.py +1 -74
- mlrun/runtimes/nuclio.py +3 -2
- mlrun/runtimes/pod.py +0 -10
- mlrun/runtimes/remotesparkjob.py +1 -15
- mlrun/runtimes/serving.py +1 -1
- mlrun/runtimes/sparkjob/__init__.py +0 -1
- mlrun/runtimes/sparkjob/abstract.py +4 -131
- mlrun/serving/states.py +1 -1
- mlrun/utils/db.py +0 -2
- mlrun/utils/helpers.py +19 -13
- mlrun/utils/notifications/notification_pusher.py +5 -25
- mlrun/utils/regex.py +7 -2
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/METADATA +24 -23
- {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/RECORD +116 -107
- {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/WHEEL +1 -1
- mlrun/mlutils/data.py +0 -160
- mlrun/mlutils/models.py +0 -78
- mlrun/mlutils/plots.py +0 -902
- {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/LICENSE +0 -0
- {mlrun-1.5.0rc1.dist-info → mlrun-1.5.0rc2.dist-info}/entry_points.txt +0 -0
- {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(
|
|
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(
|
|
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 = [
|
mlrun/api/api/endpoints/files.py
CHANGED
|
@@ -31,7 +31,13 @@ from mlrun.utils import logger
|
|
|
31
31
|
router = fastapi.APIRouter()
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
mlrun/api/api/endpoints/logs.py
CHANGED
|
@@ -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(
|
|
24
|
+
router = fastapi.APIRouter()
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
|
|
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
|
-
|
|
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(
|
|
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:
|
mlrun/api/api/endpoints/runs.py
CHANGED
|
@@ -31,7 +31,14 @@ from mlrun.utils.helpers import datetime_from_iso
|
|
|
31
31
|
router = APIRouter()
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|