34
34
import mlrun .errors
35
35
import mlrun .utils .helpers
36
36
from mlrun .kfpops import format_summary_from_kfp_run , show_kfp_run
37
- from mlrun .runtimes .nuclio .serving import serving_subkind
38
37
39
38
from .common .helpers import parse_versioned_object_uri
40
39
from .config import config as mlconf
58
57
)
59
58
from .runtimes .databricks_job .databricks_runtime import DatabricksRuntime
60
59
from .runtimes .funcdoc import update_function_entry_points
60
+ from .runtimes .nuclio .application import ApplicationRuntime
61
61
from .runtimes .utils import add_code_metadata , global_context
62
62
from .utils import (
63
63
extend_hub_uri_if_needed ,
@@ -425,19 +425,19 @@ def import_function_to_dict(url, secrets=None):
425
425
426
426
427
427
def new_function (
428
- name : str = "" ,
429
- project : str = "" ,
430
- tag : str = "" ,
431
- kind : str = "" ,
432
- command : str = "" ,
433
- image : str = "" ,
434
- args : list = None ,
435
- runtime = None ,
436
- mode = None ,
437
- handler : str = None ,
438
- source : str = None ,
428
+ name : Optional [ str ] = "" ,
429
+ project : Optional [ str ] = "" ,
430
+ tag : Optional [ str ] = "" ,
431
+ kind : Optional [ str ] = "" ,
432
+ command : Optional [ str ] = "" ,
433
+ image : Optional [ str ] = "" ,
434
+ args : Optional [ list ] = None ,
435
+ runtime : Optional [ Union [ mlrun . runtimes . BaseRuntime , dict ]] = None ,
436
+ mode : Optional [ str ] = None ,
437
+ handler : Optional [ str ] = None ,
438
+ source : Optional [ str ] = None ,
439
439
requirements : Union [str , list [str ]] = None ,
440
- kfp = None ,
440
+ kfp : Optional [ bool ] = None ,
441
441
requirements_file : str = "" ,
442
442
):
443
443
"""Create a new ML function from base properties
@@ -535,9 +535,9 @@ def new_function(
535
535
if source :
536
536
runner .spec .build .source = source
537
537
if handler :
538
- if kind == RuntimeKinds .serving :
538
+ if kind in [ RuntimeKinds .serving , RuntimeKinds . application ] :
539
539
raise MLRunInvalidArgumentError (
540
- "cannot set the handler for serving runtime"
540
+ f"Handler is not supported for { kind } runtime"
541
541
)
542
542
elif kind in RuntimeKinds .nuclio_runtimes ():
543
543
runner .spec .function_handler = handler
@@ -575,22 +575,22 @@ def _process_runtime(command, runtime, kind):
575
575
576
576
577
577
def code_to_function (
578
- name : str = "" ,
579
- project : str = "" ,
580
- tag : str = "" ,
581
- filename : str = "" ,
582
- handler : str = "" ,
583
- kind : str = "" ,
584
- image : str = None ,
585
- code_output : str = "" ,
578
+ name : Optional [ str ] = "" ,
579
+ project : Optional [ str ] = "" ,
580
+ tag : Optional [ str ] = "" ,
581
+ filename : Optional [ str ] = "" ,
582
+ handler : Optional [ str ] = "" ,
583
+ kind : Optional [ str ] = "" ,
584
+ image : Optional [ str ] = None ,
585
+ code_output : Optional [ str ] = "" ,
586
586
embed_code : bool = True ,
587
- description : str = "" ,
588
- requirements : Union [str , list [str ]] = None ,
589
- categories : list [str ] = None ,
590
- labels : dict [str , str ] = None ,
591
- with_doc : bool = True ,
592
- ignored_tags = None ,
593
- requirements_file : str = "" ,
587
+ description : Optional [ str ] = "" ,
588
+ requirements : Optional [ Union [str , list [str ] ]] = None ,
589
+ categories : Optional [ list [str ] ] = None ,
590
+ labels : Optional [ dict [str , str ] ] = None ,
591
+ with_doc : Optional [ bool ] = True ,
592
+ ignored_tags : Optional [ str ] = None ,
593
+ requirements_file : Optional [ str ] = "" ,
594
594
) -> Union [
595
595
MpiRuntimeV1Alpha1 ,
596
596
MpiRuntimeV1 ,
@@ -602,6 +602,7 @@ def code_to_function(
602
602
Spark3Runtime ,
603
603
RemoteSparkRuntime ,
604
604
DatabricksRuntime ,
605
+ ApplicationRuntime ,
605
606
]:
606
607
"""Convenience function to insert code and configure an mlrun runtime.
607
608
@@ -718,35 +719,34 @@ def update_common(fn, spec):
718
719
fn .metadata .categories = categories
719
720
fn .metadata .labels = labels or fn .metadata .labels
720
721
721
- def resolve_nuclio_subkind (kind ):
722
- is_nuclio = kind .startswith ("nuclio" )
723
- subkind = kind [kind .find (":" ) + 1 :] if is_nuclio and ":" in kind else None
724
- if kind == RuntimeKinds .serving :
725
- is_nuclio = True
726
- subkind = serving_subkind
727
- return is_nuclio , subkind
728
-
729
722
if (
730
723
not embed_code
731
724
and not code_output
732
725
and (not filename or filename .endswith (".ipynb" ))
733
726
):
734
727
raise ValueError (
735
- "a valid code file must be specified "
728
+ "A valid code file must be specified "
736
729
"when not using the embed_code option"
737
730
)
738
731
739
732
if kind == RuntimeKinds .databricks and not embed_code :
740
- raise ValueError ("databricks tasks only support embed_code=True" )
733
+ raise ValueError ("Databricks tasks only support embed_code=True" )
741
734
742
- is_nuclio , subkind = resolve_nuclio_subkind (kind )
735
+ if kind == RuntimeKinds .application :
736
+ if handler :
737
+ raise MLRunInvalidArgumentError (
738
+ "Handler is not supported for application runtime"
739
+ )
740
+ filename , handler = ApplicationRuntime .get_filename_and_handler ()
741
+
742
+ is_nuclio , sub_kind = RuntimeKinds .resolve_nuclio_sub_kind (kind )
743
743
code_origin = add_name (add_code_metadata (filename ), name )
744
744
745
745
name , spec , code = nuclio .build_file (
746
746
filename ,
747
747
name = name ,
748
748
handler = handler or "handler" ,
749
- kind = subkind ,
749
+ kind = sub_kind ,
750
750
ignored_tags = ignored_tags ,
751
751
)
752
752
spec ["spec" ]["env" ].append (
@@ -759,14 +759,14 @@ def resolve_nuclio_subkind(kind):
759
759
if not kind and spec_kind not in ["" , "Function" ]:
760
760
kind = spec_kind .lower ()
761
761
762
- # if its a nuclio subkind , redo nb parsing
763
- is_nuclio , subkind = resolve_nuclio_subkind (kind )
762
+ # if its a nuclio sub kind , redo nb parsing
763
+ is_nuclio , sub_kind = RuntimeKinds . resolve_nuclio_sub_kind (kind )
764
764
if is_nuclio :
765
765
name , spec , code = nuclio .build_file (
766
766
filename ,
767
767
name = name ,
768
768
handler = handler or "handler" ,
769
- kind = subkind ,
769
+ kind = sub_kind ,
770
770
ignored_tags = ignored_tags ,
771
771
)
772
772
@@ -780,33 +780,29 @@ def resolve_nuclio_subkind(kind):
780
780
raise ValueError ("code_output option is only used with notebooks" )
781
781
782
782
if is_nuclio :
783
- if subkind == serving_subkind :
784
- r = ServingRuntime ()
785
- else :
786
- r = RemoteRuntime ()
787
- r .spec .function_kind = subkind
788
- # default_handler is only used in :mlrun subkind, determine the handler to invoke in function.run()
789
- r .spec .default_handler = handler if subkind == "mlrun" else ""
790
- r .spec .function_handler = (
783
+ runtime = RuntimeKinds .resolve_nuclio_runtime (kind , sub_kind )
784
+ # default_handler is only used in :mlrun sub kind, determine the handler to invoke in function.run()
785
+ runtime .spec .default_handler = handler if sub_kind == "mlrun" else ""
786
+ runtime .spec .function_handler = (
791
787
handler if handler and ":" in handler else get_in (spec , "spec.handler" )
792
788
)
793
789
if not embed_code :
794
- r .spec .source = filename
790
+ runtime .spec .source = filename
795
791
nuclio_runtime = get_in (spec , "spec.runtime" )
796
792
if nuclio_runtime and not nuclio_runtime .startswith ("py" ):
797
- r .spec .nuclio_runtime = nuclio_runtime
793
+ runtime .spec .nuclio_runtime = nuclio_runtime
798
794
if not name :
799
- raise ValueError ("name must be specified " )
800
- r .metadata .name = name
801
- r .spec .build .code_origin = code_origin
802
- r .spec .build .origin_filename = filename or (name + ".ipynb" )
803
- update_common (r , spec )
804
- return r
795
+ raise ValueError ("Missing required parameter: name " )
796
+ runtime .metadata .name = name
797
+ runtime .spec .build .code_origin = code_origin
798
+ runtime .spec .build .origin_filename = filename or (name + ".ipynb" )
799
+ update_common (runtime , spec )
800
+ return runtime
805
801
806
802
if kind is None or kind in ["" , "Function" ]:
807
803
raise ValueError ("please specify the function kind" )
808
804
elif kind in RuntimeKinds .all ():
809
- r = get_runtime_class (kind )()
805
+ runtime = get_runtime_class (kind )()
810
806
else :
811
807
raise ValueError (f"unsupported runtime ({ kind } )" )
812
808
@@ -815,29 +811,29 @@ def resolve_nuclio_subkind(kind):
815
811
if not name :
816
812
raise ValueError ("name must be specified" )
817
813
h = get_in (spec , "spec.handler" , "" ).split (":" )
818
- r .handler = h [0 ] if len (h ) <= 1 else h [1 ]
819
- r .metadata = get_in (spec , "spec.metadata" )
820
- r .metadata .name = name
821
- build = r .spec .build
814
+ runtime .handler = h [0 ] if len (h ) <= 1 else h [1 ]
815
+ runtime .metadata = get_in (spec , "spec.metadata" )
816
+ runtime .metadata .name = name
817
+ build = runtime .spec .build
822
818
build .code_origin = code_origin
823
819
build .origin_filename = filename or (name + ".ipynb" )
824
820
build .extra = get_in (spec , "spec.build.extra" )
825
821
build .extra_args = get_in (spec , "spec.build.extra_args" )
826
822
build .builder_env = get_in (spec , "spec.build.builder_env" )
827
823
if not embed_code :
828
824
if code_output :
829
- r .spec .command = code_output
825
+ runtime .spec .command = code_output
830
826
else :
831
- r .spec .command = filename
827
+ runtime .spec .command = filename
832
828
833
829
build .image = get_in (spec , "spec.build.image" )
834
- update_common (r , spec )
835
- r .prepare_image_for_deploy ()
830
+ update_common (runtime , spec )
831
+ runtime .prepare_image_for_deploy ()
836
832
837
833
if with_doc :
838
- update_function_entry_points (r , code )
839
- r .spec .default_handler = handler
840
- return r
834
+ update_function_entry_points (runtime , code )
835
+ runtime .spec .default_handler = handler
836
+ return runtime
841
837
842
838
843
839
def _run_pipeline (
0 commit comments