mlrun 1.7.0rc6__py3-none-any.whl → 1.7.0rc9__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/__main__.py +2 -0
- mlrun/common/constants.py +6 -0
- mlrun/common/schemas/__init__.py +5 -0
- mlrun/common/schemas/api_gateway.py +8 -1
- mlrun/common/schemas/hub.py +7 -9
- mlrun/common/schemas/model_monitoring/__init__.py +4 -0
- mlrun/common/schemas/model_monitoring/constants.py +36 -19
- mlrun/{model_monitoring/stores/models/__init__.py → common/schemas/pagination.py} +9 -10
- mlrun/common/schemas/project.py +16 -10
- mlrun/common/types.py +7 -1
- mlrun/config.py +35 -10
- mlrun/data_types/data_types.py +4 -0
- mlrun/datastore/__init__.py +3 -7
- mlrun/datastore/alibaba_oss.py +130 -0
- mlrun/datastore/azure_blob.py +4 -5
- mlrun/datastore/base.py +22 -16
- mlrun/datastore/datastore.py +4 -0
- mlrun/datastore/datastore_profile.py +19 -1
- mlrun/datastore/google_cloud_storage.py +1 -1
- mlrun/datastore/snowflake_utils.py +43 -0
- mlrun/datastore/sources.py +11 -29
- mlrun/datastore/targets.py +131 -11
- mlrun/datastore/utils.py +10 -5
- mlrun/db/base.py +58 -6
- mlrun/db/httpdb.py +183 -77
- mlrun/db/nopdb.py +110 -0
- mlrun/feature_store/api.py +3 -2
- mlrun/feature_store/retrieval/spark_merger.py +27 -23
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/mlrun_interface.py +2 -2
- mlrun/kfpops.py +2 -5
- mlrun/launcher/base.py +1 -1
- mlrun/launcher/client.py +2 -2
- mlrun/model.py +1 -0
- mlrun/model_monitoring/__init__.py +1 -1
- mlrun/model_monitoring/api.py +104 -295
- mlrun/model_monitoring/controller.py +25 -25
- mlrun/model_monitoring/db/__init__.py +16 -0
- mlrun/model_monitoring/{stores → db/stores}/__init__.py +43 -34
- mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
- mlrun/model_monitoring/{stores/model_endpoint_store.py → db/stores/base/store.py} +47 -6
- mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +49 -0
- mlrun/model_monitoring/{stores → db/stores/sqldb}/models/base.py +76 -3
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +68 -0
- mlrun/model_monitoring/{stores → db/stores/sqldb}/models/sqlite.py +13 -1
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +662 -0
- mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
- mlrun/model_monitoring/{stores/kv_model_endpoint_store.py → db/stores/v3io_kv/kv_store.py} +134 -3
- mlrun/model_monitoring/helpers.py +3 -3
- mlrun/model_monitoring/stream_processing.py +41 -9
- mlrun/model_monitoring/tracking_policy.py +7 -1
- mlrun/model_monitoring/writer.py +4 -36
- mlrun/projects/pipelines.py +14 -2
- mlrun/projects/project.py +141 -122
- mlrun/run.py +8 -2
- mlrun/runtimes/__init__.py +16 -0
- mlrun/runtimes/base.py +10 -1
- mlrun/runtimes/kubejob.py +26 -121
- mlrun/runtimes/nuclio/api_gateway.py +243 -66
- mlrun/runtimes/nuclio/application/application.py +79 -1
- mlrun/runtimes/nuclio/application/reverse_proxy.go +9 -1
- mlrun/runtimes/nuclio/function.py +14 -8
- mlrun/runtimes/nuclio/serving.py +30 -34
- mlrun/runtimes/pod.py +171 -0
- mlrun/runtimes/utils.py +0 -28
- mlrun/serving/remote.py +2 -3
- mlrun/serving/routers.py +4 -3
- mlrun/serving/server.py +5 -7
- mlrun/serving/states.py +40 -23
- mlrun/serving/v2_serving.py +4 -3
- mlrun/utils/helpers.py +34 -0
- mlrun/utils/http.py +1 -1
- mlrun/utils/retryer.py +1 -0
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc9.dist-info}/METADATA +25 -16
- {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc9.dist-info}/RECORD +81 -75
- mlrun/model_monitoring/batch.py +0 -933
- mlrun/model_monitoring/stores/models/mysql.py +0 -34
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -382
- {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc9.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc9.dist-info}/WHEEL +0 -0
- {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc9.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc6.dist-info → mlrun-1.7.0rc9.dist-info}/top_level.txt +0 -0
mlrun/projects/project.py
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
14
15
|
import datetime
|
|
15
16
|
import getpass
|
|
16
17
|
import glob
|
|
@@ -31,7 +32,7 @@ import dotenv
|
|
|
31
32
|
import git
|
|
32
33
|
import git.exc
|
|
33
34
|
import kfp
|
|
34
|
-
import nuclio
|
|
35
|
+
import nuclio.utils
|
|
35
36
|
import requests
|
|
36
37
|
import yaml
|
|
37
38
|
|
|
@@ -44,6 +45,7 @@ import mlrun.runtimes
|
|
|
44
45
|
import mlrun.runtimes.nuclio.api_gateway
|
|
45
46
|
import mlrun.runtimes.pod
|
|
46
47
|
import mlrun.runtimes.utils
|
|
48
|
+
import mlrun.serving
|
|
47
49
|
import mlrun.utils.regex
|
|
48
50
|
from mlrun.datastore.datastore_profile import DatastoreProfile, DatastoreProfile2Json
|
|
49
51
|
from mlrun.runtimes.nuclio.function import RemoteRuntime
|
|
@@ -55,7 +57,6 @@ from ..features import Feature
|
|
|
55
57
|
from ..model import EntrypointParam, ImageBuilder, ModelObj
|
|
56
58
|
from ..model_monitoring.application import (
|
|
57
59
|
ModelMonitoringApplicationBase,
|
|
58
|
-
PushToMonitoringWriter,
|
|
59
60
|
)
|
|
60
61
|
from ..run import code_to_function, get_object, import_function, new_function
|
|
61
62
|
from ..secrets import SecretsStore
|
|
@@ -128,6 +129,7 @@ def new_project(
|
|
|
128
129
|
save: bool = True,
|
|
129
130
|
overwrite: bool = False,
|
|
130
131
|
parameters: dict = None,
|
|
132
|
+
default_function_node_selector: dict = None,
|
|
131
133
|
) -> "MlrunProject":
|
|
132
134
|
"""Create a new MLRun project, optionally load it from a yaml/zip/git template
|
|
133
135
|
|
|
@@ -181,6 +183,7 @@ def new_project(
|
|
|
181
183
|
:param overwrite: overwrite project using 'cascade' deletion strategy (deletes project resources)
|
|
182
184
|
if project with name exists
|
|
183
185
|
:param parameters: key/value pairs to add to the project.spec.params
|
|
186
|
+
:param default_function_node_selector: defines the default node selector for scheduling functions within the project
|
|
184
187
|
|
|
185
188
|
:returns: project object
|
|
186
189
|
"""
|
|
@@ -227,6 +230,11 @@ def new_project(
|
|
|
227
230
|
project.spec.origin_url = url
|
|
228
231
|
if description:
|
|
229
232
|
project.spec.description = description
|
|
233
|
+
|
|
234
|
+
if default_function_node_selector:
|
|
235
|
+
for key, val in default_function_node_selector.items():
|
|
236
|
+
project.spec.default_function_node_selector[key] = val
|
|
237
|
+
|
|
230
238
|
if parameters:
|
|
231
239
|
# Enable setting project parameters at load time, can be used to customize the project_setup
|
|
232
240
|
for key, val in parameters.items():
|
|
@@ -760,6 +768,7 @@ class ProjectSpec(ModelObj):
|
|
|
760
768
|
default_image=None,
|
|
761
769
|
build=None,
|
|
762
770
|
custom_packagers: list[tuple[str, bool]] = None,
|
|
771
|
+
default_function_node_selector=None,
|
|
763
772
|
):
|
|
764
773
|
self.repo = None
|
|
765
774
|
|
|
@@ -799,6 +808,7 @@ class ProjectSpec(ModelObj):
|
|
|
799
808
|
# in a tuple where the first index is the packager module's path (str) and the second is a flag (bool) for
|
|
800
809
|
# whether it is mandatory for a run (raise exception on collection error) or not.
|
|
801
810
|
self.custom_packagers = custom_packagers or []
|
|
811
|
+
self.default_function_node_selector = default_function_node_selector or {}
|
|
802
812
|
|
|
803
813
|
@property
|
|
804
814
|
def source(self) -> str:
|
|
@@ -1844,10 +1854,10 @@ class MlrunProject(ModelObj):
|
|
|
1844
1854
|
monitoring application's constructor.
|
|
1845
1855
|
"""
|
|
1846
1856
|
|
|
1847
|
-
if name in mm_constants.MonitoringFunctionNames.
|
|
1857
|
+
if name in mm_constants.MonitoringFunctionNames.list():
|
|
1848
1858
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
1849
|
-
f"
|
|
1850
|
-
f"{mm_constants.MonitoringFunctionNames.
|
|
1859
|
+
f"An application cannot have the following names: "
|
|
1860
|
+
f"{mm_constants.MonitoringFunctionNames.list()}"
|
|
1851
1861
|
)
|
|
1852
1862
|
function_object: RemoteRuntime = None
|
|
1853
1863
|
(
|
|
@@ -1866,16 +1876,6 @@ class MlrunProject(ModelObj):
|
|
|
1866
1876
|
requirements_file,
|
|
1867
1877
|
**application_kwargs,
|
|
1868
1878
|
)
|
|
1869
|
-
models_names = "all"
|
|
1870
|
-
function_object.set_label(
|
|
1871
|
-
mm_constants.ModelMonitoringAppLabel.KEY,
|
|
1872
|
-
mm_constants.ModelMonitoringAppLabel.VAL,
|
|
1873
|
-
)
|
|
1874
|
-
function_object.set_label("models", models_names)
|
|
1875
|
-
|
|
1876
|
-
if not mlrun.mlconf.is_ce_mode():
|
|
1877
|
-
function_object.apply(mlrun.mount_v3io())
|
|
1878
|
-
|
|
1879
1879
|
# save to project spec
|
|
1880
1880
|
self.spec.set_function(resolved_function_name, function_object, func)
|
|
1881
1881
|
|
|
@@ -1934,49 +1934,38 @@ class MlrunProject(ModelObj):
|
|
|
1934
1934
|
|
|
1935
1935
|
def _instantiate_model_monitoring_function(
|
|
1936
1936
|
self,
|
|
1937
|
-
func: typing.Union[str, mlrun.runtimes.BaseRuntime] = None,
|
|
1938
|
-
application_class: typing.Union[
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1937
|
+
func: typing.Union[str, mlrun.runtimes.BaseRuntime, None] = None,
|
|
1938
|
+
application_class: typing.Union[
|
|
1939
|
+
str, ModelMonitoringApplicationBase, None
|
|
1940
|
+
] = None,
|
|
1941
|
+
name: typing.Optional[str] = None,
|
|
1942
|
+
image: typing.Optional[str] = None,
|
|
1943
|
+
handler: typing.Optional[str] = None,
|
|
1944
|
+
with_repo: typing.Optional[bool] = None,
|
|
1945
|
+
tag: typing.Optional[str] = None,
|
|
1946
|
+
requirements: typing.Union[str, list[str], None] = None,
|
|
1945
1947
|
requirements_file: str = "",
|
|
1946
1948
|
**application_kwargs,
|
|
1947
1949
|
) -> tuple[str, mlrun.runtimes.BaseRuntime, dict]:
|
|
1950
|
+
import mlrun.model_monitoring.api
|
|
1951
|
+
|
|
1948
1952
|
function_object: RemoteRuntime = None
|
|
1949
1953
|
kind = None
|
|
1950
1954
|
if (isinstance(func, str) or func is None) and application_class is not None:
|
|
1951
|
-
kind =
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1955
|
+
kind = mlrun.run.RuntimeKinds.serving
|
|
1956
|
+
func = mlrun.model_monitoring.api._create_model_monitoring_function_base(
|
|
1957
|
+
project=self.name,
|
|
1958
|
+
func=func,
|
|
1959
|
+
application_class=application_class,
|
|
1956
1960
|
name=name,
|
|
1957
|
-
project=self.metadata.name,
|
|
1958
|
-
tag=tag,
|
|
1959
|
-
kind=kind,
|
|
1960
1961
|
image=image,
|
|
1962
|
+
tag=tag,
|
|
1961
1963
|
requirements=requirements,
|
|
1962
1964
|
requirements_file=requirements_file,
|
|
1965
|
+
**application_kwargs,
|
|
1963
1966
|
)
|
|
1964
|
-
graph = func.set_topology("flow")
|
|
1965
|
-
if isinstance(application_class, str):
|
|
1966
|
-
first_step = graph.to(
|
|
1967
|
-
class_name=application_class, **application_kwargs
|
|
1968
|
-
)
|
|
1969
|
-
else:
|
|
1970
|
-
first_step = graph.to(class_name=application_class)
|
|
1971
|
-
first_step.to(
|
|
1972
|
-
class_name=PushToMonitoringWriter(
|
|
1973
|
-
project=self.metadata.name,
|
|
1974
|
-
writer_application_name=mm_constants.MonitoringFunctionNames.WRITER,
|
|
1975
|
-
stream_uri=None,
|
|
1976
|
-
),
|
|
1977
|
-
).respond()
|
|
1978
1967
|
elif isinstance(func, str) and isinstance(handler, str):
|
|
1979
|
-
kind =
|
|
1968
|
+
kind = mlrun.run.RuntimeKinds.nuclio
|
|
1980
1969
|
|
|
1981
1970
|
(
|
|
1982
1971
|
resolved_function_name,
|
|
@@ -1994,12 +1983,10 @@ class MlrunProject(ModelObj):
|
|
|
1994
1983
|
requirements,
|
|
1995
1984
|
requirements_file,
|
|
1996
1985
|
)
|
|
1997
|
-
models_names = "all"
|
|
1998
1986
|
function_object.set_label(
|
|
1999
1987
|
mm_constants.ModelMonitoringAppLabel.KEY,
|
|
2000
1988
|
mm_constants.ModelMonitoringAppLabel.VAL,
|
|
2001
1989
|
)
|
|
2002
|
-
function_object.set_label("models", models_names)
|
|
2003
1990
|
|
|
2004
1991
|
if not mlrun.mlconf.is_ce_mode():
|
|
2005
1992
|
function_object.apply(mlrun.mount_v3io())
|
|
@@ -2029,8 +2016,6 @@ class MlrunProject(ModelObj):
|
|
|
2029
2016
|
stream & histogram data drift functions, which are real time nuclio
|
|
2030
2017
|
functions. By default, the image is mlrun/mlrun.
|
|
2031
2018
|
:param deploy_histogram_data_drift_app: If true, deploy the default histogram-based data drift application.
|
|
2032
|
-
|
|
2033
|
-
:returns: model monitoring controller job as a dictionary.
|
|
2034
2019
|
"""
|
|
2035
2020
|
if default_controller_image != "mlrun/mlrun":
|
|
2036
2021
|
# TODO: Remove this in 1.9.0
|
|
@@ -2045,18 +2030,24 @@ class MlrunProject(ModelObj):
|
|
|
2045
2030
|
project=self.name,
|
|
2046
2031
|
image=image,
|
|
2047
2032
|
base_period=base_period,
|
|
2033
|
+
deploy_histogram_data_drift_app=deploy_histogram_data_drift_app,
|
|
2048
2034
|
)
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2035
|
+
|
|
2036
|
+
def deploy_histogram_data_drift_app(
|
|
2037
|
+
self,
|
|
2038
|
+
*,
|
|
2039
|
+
image: str = "mlrun/mlrun",
|
|
2040
|
+
db: Optional[mlrun.db.RunDBInterface] = None,
|
|
2041
|
+
) -> None:
|
|
2042
|
+
"""
|
|
2043
|
+
Deploy the histogram data drift application.
|
|
2044
|
+
|
|
2045
|
+
:param image: The image on which the application will run.
|
|
2046
|
+
:param db: An optional DB object.
|
|
2047
|
+
"""
|
|
2048
|
+
if db is None:
|
|
2049
|
+
db = mlrun.db.get_run_db(secrets=self._secrets)
|
|
2050
|
+
db.deploy_histogram_data_drift_app(project=self.name, image=image)
|
|
2060
2051
|
|
|
2061
2052
|
def update_model_monitoring_controller(
|
|
2062
2053
|
self,
|
|
@@ -2081,26 +2072,28 @@ class MlrunProject(ModelObj):
|
|
|
2081
2072
|
image=image,
|
|
2082
2073
|
)
|
|
2083
2074
|
|
|
2084
|
-
def disable_model_monitoring(
|
|
2075
|
+
def disable_model_monitoring(
|
|
2076
|
+
self, *, delete_histogram_data_drift_app: bool = True
|
|
2077
|
+
) -> None:
|
|
2078
|
+
"""
|
|
2079
|
+
Note: This method is currently not advised for use. See ML-3432.
|
|
2080
|
+
Disable model monitoring by deleting the underlying functions infrastructure from MLRun database.
|
|
2081
|
+
|
|
2082
|
+
:param delete_histogram_data_drift_app: Whether to delete the histogram data drift app.
|
|
2083
|
+
"""
|
|
2085
2084
|
db = mlrun.db.get_run_db(secrets=self._secrets)
|
|
2086
|
-
|
|
2087
|
-
project=self.name,
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
name=mm_constants.MonitoringFunctionNames.WRITER,
|
|
2093
|
-
)
|
|
2094
|
-
db.delete_function(
|
|
2095
|
-
project=self.name,
|
|
2096
|
-
name=mm_constants.MonitoringFunctionNames.STREAM,
|
|
2097
|
-
)
|
|
2085
|
+
for fn_name in mm_constants.MonitoringFunctionNames.list():
|
|
2086
|
+
db.delete_function(project=self.name, name=fn_name)
|
|
2087
|
+
if delete_histogram_data_drift_app:
|
|
2088
|
+
db.delete_function(
|
|
2089
|
+
project=self.name, name=mm_constants.MLRUN_HISTOGRAM_DATA_DRIFT_APP_NAME
|
|
2090
|
+
)
|
|
2098
2091
|
|
|
2099
2092
|
def set_function(
|
|
2100
2093
|
self,
|
|
2101
2094
|
func: typing.Union[str, mlrun.runtimes.BaseRuntime] = None,
|
|
2102
2095
|
name: str = "",
|
|
2103
|
-
kind: str = "",
|
|
2096
|
+
kind: str = "job",
|
|
2104
2097
|
image: str = None,
|
|
2105
2098
|
handler: str = None,
|
|
2106
2099
|
with_repo: bool = None,
|
|
@@ -2187,16 +2180,13 @@ class MlrunProject(ModelObj):
|
|
|
2187
2180
|
if func is None and not _has_module(handler, kind):
|
|
2188
2181
|
# if function path is not provided and it is not a module (no ".")
|
|
2189
2182
|
# use the current notebook as default
|
|
2190
|
-
if
|
|
2191
|
-
|
|
2192
|
-
"Function path or module must be specified (when not running inside a Notebook)"
|
|
2193
|
-
)
|
|
2194
|
-
from IPython import get_ipython
|
|
2183
|
+
if is_ipython:
|
|
2184
|
+
from IPython import get_ipython
|
|
2195
2185
|
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2186
|
+
kernel = get_ipython()
|
|
2187
|
+
func = nuclio.utils.notebook_file_name(kernel)
|
|
2188
|
+
if func.startswith(path.abspath(self.spec.context)):
|
|
2189
|
+
func = path.relpath(func, self.spec.context)
|
|
2200
2190
|
|
|
2201
2191
|
func = func or ""
|
|
2202
2192
|
|
|
@@ -2747,40 +2737,41 @@ class MlrunProject(ModelObj):
|
|
|
2747
2737
|
cleanup_ttl: int = None,
|
|
2748
2738
|
notifications: list[mlrun.model.Notification] = None,
|
|
2749
2739
|
) -> _PipelineRunStatus:
|
|
2750
|
-
"""
|
|
2751
|
-
|
|
2752
|
-
:param name:
|
|
2753
|
-
:param workflow_path:
|
|
2754
|
-
|
|
2755
|
-
:param
|
|
2756
|
-
|
|
2757
|
-
:param
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
:param
|
|
2761
|
-
|
|
2762
|
-
:param
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
:param
|
|
2766
|
-
:param engine: workflow engine running the workflow.
|
|
2767
|
-
supported values are 'kfp' (default), 'local' or 'remote'.
|
|
2768
|
-
for setting engine for remote running use 'remote:local' or 'remote:kfp'.
|
|
2769
|
-
:param local: run local pipeline with local functions (set local=True in function.run())
|
|
2740
|
+
"""Run a workflow using kubeflow pipelines
|
|
2741
|
+
|
|
2742
|
+
:param name: Name of the workflow
|
|
2743
|
+
:param workflow_path: URL to a workflow file, if not a project workflow
|
|
2744
|
+
:param arguments: Kubeflow pipelines arguments (parameters)
|
|
2745
|
+
:param artifact_path: Target path/URL for workflow artifacts, the string '{{workflow.uid}}' will be
|
|
2746
|
+
replaced by workflow id.
|
|
2747
|
+
:param workflow_handler: Workflow function handler (for running workflow function directly)
|
|
2748
|
+
:param namespace: Kubernetes namespace if other than default
|
|
2749
|
+
:param sync: Force functions sync before run
|
|
2750
|
+
:param watch: Wait for pipeline completion
|
|
2751
|
+
:param dirty: Allow running the workflow when the git repo is dirty
|
|
2752
|
+
:param engine: Workflow engine running the workflow.
|
|
2753
|
+
Supported values are 'kfp' (default), 'local' or 'remote'.
|
|
2754
|
+
For setting engine for remote running use 'remote:local' or 'remote:kfp'.
|
|
2755
|
+
:param local: Run local pipeline with local functions (set local=True in function.run())
|
|
2770
2756
|
:param schedule: ScheduleCronTrigger class instance or a standard crontab expression string
|
|
2771
2757
|
(which will be converted to the class using its `from_crontab` constructor),
|
|
2772
2758
|
see this link for help:
|
|
2773
2759
|
https://apscheduler.readthedocs.io/en/3.x/modules/triggers/cron.html#module-apscheduler.triggers.cron
|
|
2774
2760
|
for using the pre-defined workflow's schedule, set `schedule=True`
|
|
2775
|
-
:param timeout:
|
|
2776
|
-
:param source:
|
|
2777
|
-
|
|
2761
|
+
:param timeout: Timeout in seconds to wait for pipeline completion (watch will be activated)
|
|
2762
|
+
:param source: Source to use instead of the actual `project.spec.source` (used when engine is remote).
|
|
2763
|
+
Can be a one of:
|
|
2764
|
+
1. Remote URL which is loaded dynamically to the workflow runner.
|
|
2765
|
+
2. A path to the project's context on the workflow runner's image.
|
|
2766
|
+
Path can be absolute or relative to `project.spec.build.source_code_target_dir` if defined
|
|
2767
|
+
(enriched when building a project image with source, see `MlrunProject.build_image`).
|
|
2768
|
+
For other engines the source is used to validate that the code is up-to-date.
|
|
2778
2769
|
:param cleanup_ttl:
|
|
2779
|
-
|
|
2780
|
-
|
|
2770
|
+
Pipeline cleanup ttl in secs (time to wait after workflow completion, at which point the
|
|
2771
|
+
Workflow and all its resources are deleted)
|
|
2781
2772
|
:param notifications:
|
|
2782
|
-
|
|
2783
|
-
:returns:
|
|
2773
|
+
List of notifications to send for workflow completion
|
|
2774
|
+
:returns: Run id
|
|
2784
2775
|
"""
|
|
2785
2776
|
|
|
2786
2777
|
arguments = arguments or {}
|
|
@@ -3179,6 +3170,7 @@ class MlrunProject(ModelObj):
|
|
|
3179
3170
|
requirements_file: str = None,
|
|
3180
3171
|
builder_env: dict = None,
|
|
3181
3172
|
extra_args: str = None,
|
|
3173
|
+
source_code_target_dir: str = None,
|
|
3182
3174
|
):
|
|
3183
3175
|
"""specify builder configuration for the project
|
|
3184
3176
|
|
|
@@ -3199,6 +3191,8 @@ class MlrunProject(ModelObj):
|
|
|
3199
3191
|
e.g. builder_env={"GIT_TOKEN": token}, does not work yet in KFP
|
|
3200
3192
|
:param extra_args: A string containing additional builder arguments in the format of command-line options,
|
|
3201
3193
|
e.g. extra_args="--skip-tls-verify --build-arg A=val"
|
|
3194
|
+
:param source_code_target_dir: Path on the image where source code would be extracted
|
|
3195
|
+
(by default `/home/mlrun_code`)
|
|
3202
3196
|
"""
|
|
3203
3197
|
if not overwrite_build_params:
|
|
3204
3198
|
# TODO: change overwrite_build_params default to True in 1.8.0
|
|
@@ -3222,6 +3216,7 @@ class MlrunProject(ModelObj):
|
|
|
3222
3216
|
overwrite=overwrite_build_params,
|
|
3223
3217
|
builder_env=builder_env,
|
|
3224
3218
|
extra_args=extra_args,
|
|
3219
|
+
source_code_target_dir=source_code_target_dir,
|
|
3225
3220
|
)
|
|
3226
3221
|
|
|
3227
3222
|
if set_as_default and image != self.default_image:
|
|
@@ -3268,7 +3263,7 @@ class MlrunProject(ModelObj):
|
|
|
3268
3263
|
* False: The new params are merged with the existing
|
|
3269
3264
|
* True: The existing params are replaced by the new ones
|
|
3270
3265
|
:param extra_args: A string containing additional builder arguments in the format of command-line options,
|
|
3271
|
-
e.g. extra_args="--skip-tls-verify --build-arg A=val"
|
|
3266
|
+
e.g. extra_args="--skip-tls-verify --build-arg A=val"
|
|
3272
3267
|
:param target_dir: Path on the image where source code would be extracted (by default `/home/mlrun_code`)
|
|
3273
3268
|
"""
|
|
3274
3269
|
if not base_image:
|
|
@@ -3336,6 +3331,11 @@ class MlrunProject(ModelObj):
|
|
|
3336
3331
|
force_build=True,
|
|
3337
3332
|
)
|
|
3338
3333
|
|
|
3334
|
+
# Get the enriched target dir from the function
|
|
3335
|
+
self.spec.build.source_code_target_dir = (
|
|
3336
|
+
function.spec.build.source_code_target_dir
|
|
3337
|
+
)
|
|
3338
|
+
|
|
3339
3339
|
try:
|
|
3340
3340
|
mlrun.db.get_run_db(secrets=self._secrets).delete_function(
|
|
3341
3341
|
name=function.metadata.name
|
|
@@ -3344,7 +3344,7 @@ class MlrunProject(ModelObj):
|
|
|
3344
3344
|
logger.warning(
|
|
3345
3345
|
f"Image was successfully built, but failed to delete temporary function {function.metadata.name}."
|
|
3346
3346
|
" To remove the function, attempt to manually delete it.",
|
|
3347
|
-
exc=
|
|
3347
|
+
exc=mlrun.errors.err_to_str(exc),
|
|
3348
3348
|
)
|
|
3349
3349
|
|
|
3350
3350
|
return result
|
|
@@ -3692,7 +3692,10 @@ class MlrunProject(ModelObj):
|
|
|
3692
3692
|
self.spec.remove_custom_packager(packager=packager)
|
|
3693
3693
|
|
|
3694
3694
|
def store_api_gateway(
|
|
3695
|
-
self,
|
|
3695
|
+
self,
|
|
3696
|
+
api_gateway: mlrun.runtimes.nuclio.api_gateway.APIGateway,
|
|
3697
|
+
wait_for_readiness=True,
|
|
3698
|
+
max_wait_time=90,
|
|
3696
3699
|
) -> mlrun.runtimes.nuclio.api_gateway.APIGateway:
|
|
3697
3700
|
"""
|
|
3698
3701
|
Creates or updates a Nuclio API Gateway using the provided APIGateway object.
|
|
@@ -3703,7 +3706,11 @@ class MlrunProject(ModelObj):
|
|
|
3703
3706
|
Nuclio docs here: https://docs.nuclio.io/en/latest/reference/api-gateway/http.html
|
|
3704
3707
|
|
|
3705
3708
|
:param api_gateway: An instance of :py:class:`~mlrun.runtimes.nuclio.APIGateway` representing the configuration
|
|
3706
|
-
of the API Gateway to be created
|
|
3709
|
+
of the API Gateway to be created or updated.
|
|
3710
|
+
:param wait_for_readiness: (Optional) A boolean indicating whether to wait for the API Gateway to become ready
|
|
3711
|
+
after creation or update (default is True)
|
|
3712
|
+
:param max_wait_time: (Optional) Maximum time to wait for API Gateway readiness in seconds (default is 90s)
|
|
3713
|
+
|
|
3707
3714
|
|
|
3708
3715
|
@return: An instance of :py:class:`~mlrun.runtimes.nuclio.APIGateway` with all fields populated based on the
|
|
3709
3716
|
information retrieved from the Nuclio API
|
|
@@ -3719,6 +3726,9 @@ class MlrunProject(ModelObj):
|
|
|
3719
3726
|
api_gateway = mlrun.runtimes.nuclio.api_gateway.APIGateway.from_scheme(
|
|
3720
3727
|
api_gateway_json
|
|
3721
3728
|
)
|
|
3729
|
+
if wait_for_readiness:
|
|
3730
|
+
api_gateway.wait_for_readiness(max_wait_time=max_wait_time)
|
|
3731
|
+
|
|
3722
3732
|
return api_gateway
|
|
3723
3733
|
|
|
3724
3734
|
def list_api_gateways(self) -> list[mlrun.runtimes.nuclio.api_gateway.APIGateway]:
|
|
@@ -3747,7 +3757,20 @@ class MlrunProject(ModelObj):
|
|
|
3747
3757
|
mlrun.runtimes.nuclio.APIGateway: An instance of APIGateway.
|
|
3748
3758
|
"""
|
|
3749
3759
|
|
|
3750
|
-
|
|
3760
|
+
gateway = mlrun.db.get_run_db().get_api_gateway(name=name, project=self.name)
|
|
3761
|
+
return mlrun.runtimes.nuclio.api_gateway.APIGateway.from_scheme(gateway)
|
|
3762
|
+
|
|
3763
|
+
def delete_api_gateway(
|
|
3764
|
+
self,
|
|
3765
|
+
name: str,
|
|
3766
|
+
):
|
|
3767
|
+
"""
|
|
3768
|
+
Deletes an API gateway by name.
|
|
3769
|
+
|
|
3770
|
+
:param name: The name of the API gateway to delete.
|
|
3771
|
+
"""
|
|
3772
|
+
|
|
3773
|
+
mlrun.db.get_run_db().delete_api_gateway(name=name, project=self.name)
|
|
3751
3774
|
|
|
3752
3775
|
def _run_authenticated_git_action(
|
|
3753
3776
|
self,
|
|
@@ -3925,10 +3948,6 @@ def _init_function_from_dict(
|
|
|
3925
3948
|
tag = f.get("tag", None)
|
|
3926
3949
|
|
|
3927
3950
|
has_module = _has_module(handler, kind)
|
|
3928
|
-
if not url and "spec" not in f and not has_module:
|
|
3929
|
-
# function must point to a file or a module or have a spec
|
|
3930
|
-
raise ValueError("Function missing a url or a spec or a module")
|
|
3931
|
-
|
|
3932
3951
|
relative_url = url
|
|
3933
3952
|
url, in_context = project.get_item_absolute_path(url)
|
|
3934
3953
|
|
|
@@ -3988,7 +4007,7 @@ def _init_function_from_dict(
|
|
|
3988
4007
|
tag=tag,
|
|
3989
4008
|
)
|
|
3990
4009
|
|
|
3991
|
-
elif
|
|
4010
|
+
elif kind in mlrun.runtimes.RuntimeKinds.nuclio_runtimes():
|
|
3992
4011
|
func = new_function(
|
|
3993
4012
|
name,
|
|
3994
4013
|
command=relative_url,
|
|
@@ -3997,7 +4016,7 @@ def _init_function_from_dict(
|
|
|
3997
4016
|
handler=handler,
|
|
3998
4017
|
tag=tag,
|
|
3999
4018
|
)
|
|
4000
|
-
if kind != mlrun.runtimes.RuntimeKinds.application:
|
|
4019
|
+
if image and kind != mlrun.runtimes.RuntimeKinds.application:
|
|
4001
4020
|
logger.info("Function code not specified, setting entry point to image")
|
|
4002
4021
|
func.from_image(image)
|
|
4003
4022
|
else:
|
mlrun/run.py
CHANGED
|
@@ -389,6 +389,8 @@ def import_function_to_dict(url, secrets=None):
|
|
|
389
389
|
code = get_in(runtime, "spec.build.functionSourceCode")
|
|
390
390
|
update_in(runtime, "metadata.build.code_origin", url)
|
|
391
391
|
cmd = code_file = get_in(runtime, "spec.command", "")
|
|
392
|
+
# use kind = "job" by default if not specified
|
|
393
|
+
runtime.setdefault("kind", "job")
|
|
392
394
|
if " " in cmd:
|
|
393
395
|
code_file = cmd[: cmd.find(" ")]
|
|
394
396
|
if runtime["kind"] in ["", "local"]:
|
|
@@ -535,7 +537,7 @@ def new_function(
|
|
|
535
537
|
if source:
|
|
536
538
|
runner.spec.build.source = source
|
|
537
539
|
if handler:
|
|
538
|
-
if kind in
|
|
540
|
+
if kind in RuntimeKinds.handlerless_runtimes():
|
|
539
541
|
raise MLRunInvalidArgumentError(
|
|
540
542
|
f"Handler is not supported for {kind} runtime"
|
|
541
543
|
)
|
|
@@ -628,6 +630,8 @@ def code_to_function(
|
|
|
628
630
|
- mpijob: run distributed Horovod jobs over the MPI job operator
|
|
629
631
|
- spark: run distributed Spark job using Spark Kubernetes Operator
|
|
630
632
|
- remote-spark: run distributed Spark job on remote Spark service
|
|
633
|
+
- databricks: run code on Databricks cluster (python scripts, Spark etc.)
|
|
634
|
+
- application: run a long living application (e.g. a web server, UI, etc.)
|
|
631
635
|
|
|
632
636
|
Learn more about [Kinds of function (runtimes)](../concepts/functions-overview.html).
|
|
633
637
|
|
|
@@ -847,6 +851,7 @@ def _run_pipeline(
|
|
|
847
851
|
ops=None,
|
|
848
852
|
url=None,
|
|
849
853
|
cleanup_ttl=None,
|
|
854
|
+
timeout=60,
|
|
850
855
|
):
|
|
851
856
|
"""remote KubeFlow pipeline execution
|
|
852
857
|
|
|
@@ -884,6 +889,7 @@ def _run_pipeline(
|
|
|
884
889
|
ops=ops,
|
|
885
890
|
artifact_path=artifact_path,
|
|
886
891
|
cleanup_ttl=cleanup_ttl,
|
|
892
|
+
timeout=timeout,
|
|
887
893
|
)
|
|
888
894
|
logger.info(f"Pipeline run id={pipeline_run_id}, check UI for progress")
|
|
889
895
|
return pipeline_run_id
|
|
@@ -961,7 +967,7 @@ def wait_for_pipeline_completion(
|
|
|
961
967
|
show_kfp_run(resp)
|
|
962
968
|
|
|
963
969
|
status = resp["run"]["status"] if resp else "unknown"
|
|
964
|
-
message = resp["run"].get("message", "")
|
|
970
|
+
message = resp["run"].get("message", "") if resp else ""
|
|
965
971
|
if expected_statuses:
|
|
966
972
|
if status not in expected_statuses:
|
|
967
973
|
raise RuntimeError(
|
mlrun/runtimes/__init__.py
CHANGED
|
@@ -154,6 +154,22 @@ class RuntimeKinds:
|
|
|
154
154
|
RuntimeKinds.application,
|
|
155
155
|
]
|
|
156
156
|
|
|
157
|
+
@staticmethod
|
|
158
|
+
def pure_nuclio_deployed_runtimes():
|
|
159
|
+
return [
|
|
160
|
+
RuntimeKinds.remote,
|
|
161
|
+
RuntimeKinds.nuclio,
|
|
162
|
+
RuntimeKinds.serving,
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
@staticmethod
|
|
166
|
+
def handlerless_runtimes():
|
|
167
|
+
return [
|
|
168
|
+
RuntimeKinds.serving,
|
|
169
|
+
# Application runtime handler is internal reverse proxy
|
|
170
|
+
RuntimeKinds.application,
|
|
171
|
+
]
|
|
172
|
+
|
|
157
173
|
@staticmethod
|
|
158
174
|
def local_runtimes():
|
|
159
175
|
return [
|
mlrun/runtimes/base.py
CHANGED
|
@@ -23,6 +23,7 @@ from typing import Callable, Optional, Union
|
|
|
23
23
|
import requests.exceptions
|
|
24
24
|
from nuclio.build import mlrun_footer
|
|
25
25
|
|
|
26
|
+
import mlrun.common.constants
|
|
26
27
|
import mlrun.common.schemas
|
|
27
28
|
import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
28
29
|
import mlrun.db
|
|
@@ -634,7 +635,9 @@ class BaseRuntime(ModelObj):
|
|
|
634
635
|
image = image or self.spec.image or ""
|
|
635
636
|
|
|
636
637
|
image = enrich_image_url(image, client_version, client_python_version)
|
|
637
|
-
if not image.startswith(
|
|
638
|
+
if not image.startswith(
|
|
639
|
+
mlrun.common.constants.IMAGE_NAME_ENRICH_REGISTRY_PREFIX
|
|
640
|
+
):
|
|
638
641
|
return image
|
|
639
642
|
registry, repository = get_parsed_docker_registry()
|
|
640
643
|
if registry:
|
|
@@ -840,6 +843,12 @@ class BaseRuntime(ModelObj):
|
|
|
840
843
|
or (build.source and not build.load_source_on_run)
|
|
841
844
|
)
|
|
842
845
|
|
|
846
|
+
def enrich_runtime_spec(
|
|
847
|
+
self,
|
|
848
|
+
project_node_selector: dict[str, str],
|
|
849
|
+
):
|
|
850
|
+
pass
|
|
851
|
+
|
|
843
852
|
def prepare_image_for_deploy(self):
|
|
844
853
|
"""
|
|
845
854
|
if a function has a 'spec.image' it is considered to be deployed,
|