mlrun 1.7.0rc14__py3-none-any.whl → 1.7.0rc21__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 (152) hide show
  1. mlrun/__init__.py +10 -1
  2. mlrun/__main__.py +23 -111
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +144 -0
  5. mlrun/api/schemas/__init__.py +4 -3
  6. mlrun/artifacts/__init__.py +8 -3
  7. mlrun/artifacts/base.py +36 -253
  8. mlrun/artifacts/dataset.py +9 -190
  9. mlrun/artifacts/manager.py +46 -42
  10. mlrun/artifacts/model.py +9 -141
  11. mlrun/artifacts/plots.py +14 -375
  12. mlrun/common/constants.py +65 -3
  13. mlrun/common/formatters/__init__.py +19 -0
  14. mlrun/{runtimes/mpijob/v1alpha1.py → common/formatters/artifact.py} +6 -14
  15. mlrun/common/formatters/base.py +113 -0
  16. mlrun/common/formatters/function.py +46 -0
  17. mlrun/common/formatters/pipeline.py +53 -0
  18. mlrun/common/formatters/project.py +51 -0
  19. mlrun/{runtimes → common/runtimes}/constants.py +32 -4
  20. mlrun/common/schemas/__init__.py +10 -5
  21. mlrun/common/schemas/alert.py +92 -11
  22. mlrun/common/schemas/api_gateway.py +56 -0
  23. mlrun/common/schemas/artifact.py +15 -5
  24. mlrun/common/schemas/auth.py +2 -0
  25. mlrun/common/schemas/client_spec.py +1 -0
  26. mlrun/common/schemas/frontend_spec.py +1 -0
  27. mlrun/common/schemas/function.py +4 -0
  28. mlrun/common/schemas/model_monitoring/__init__.py +15 -3
  29. mlrun/common/schemas/model_monitoring/constants.py +58 -7
  30. mlrun/common/schemas/model_monitoring/grafana.py +9 -5
  31. mlrun/common/schemas/model_monitoring/model_endpoints.py +86 -2
  32. mlrun/common/schemas/pipeline.py +0 -9
  33. mlrun/common/schemas/project.py +5 -11
  34. mlrun/common/types.py +1 -0
  35. mlrun/config.py +27 -9
  36. mlrun/data_types/to_pandas.py +9 -9
  37. mlrun/datastore/base.py +41 -9
  38. mlrun/datastore/datastore.py +6 -2
  39. mlrun/datastore/datastore_profile.py +56 -4
  40. mlrun/datastore/inmem.py +2 -2
  41. mlrun/datastore/redis.py +2 -2
  42. mlrun/datastore/s3.py +5 -0
  43. mlrun/datastore/sources.py +147 -7
  44. mlrun/datastore/store_resources.py +7 -7
  45. mlrun/datastore/targets.py +110 -42
  46. mlrun/datastore/utils.py +42 -0
  47. mlrun/db/base.py +54 -10
  48. mlrun/db/httpdb.py +282 -79
  49. mlrun/db/nopdb.py +52 -10
  50. mlrun/errors.py +11 -0
  51. mlrun/execution.py +24 -9
  52. mlrun/feature_store/__init__.py +0 -2
  53. mlrun/feature_store/api.py +12 -47
  54. mlrun/feature_store/feature_set.py +9 -0
  55. mlrun/feature_store/feature_vector.py +8 -0
  56. mlrun/feature_store/ingestion.py +7 -6
  57. mlrun/feature_store/retrieval/base.py +9 -4
  58. mlrun/feature_store/retrieval/conversion.py +9 -9
  59. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  60. mlrun/feature_store/retrieval/job.py +9 -3
  61. mlrun/feature_store/retrieval/local_merger.py +2 -0
  62. mlrun/feature_store/retrieval/spark_merger.py +16 -0
  63. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
  64. mlrun/frameworks/parallel_coordinates.py +2 -1
  65. mlrun/frameworks/tf_keras/__init__.py +4 -1
  66. mlrun/k8s_utils.py +10 -11
  67. mlrun/launcher/base.py +4 -3
  68. mlrun/launcher/client.py +5 -3
  69. mlrun/launcher/local.py +8 -2
  70. mlrun/launcher/remote.py +8 -2
  71. mlrun/lists.py +6 -2
  72. mlrun/model.py +45 -21
  73. mlrun/model_monitoring/__init__.py +1 -1
  74. mlrun/model_monitoring/api.py +41 -18
  75. mlrun/model_monitoring/application.py +5 -305
  76. mlrun/model_monitoring/applications/__init__.py +11 -0
  77. mlrun/model_monitoring/applications/_application_steps.py +157 -0
  78. mlrun/model_monitoring/applications/base.py +280 -0
  79. mlrun/model_monitoring/applications/context.py +214 -0
  80. mlrun/model_monitoring/applications/evidently_base.py +211 -0
  81. mlrun/model_monitoring/applications/histogram_data_drift.py +132 -91
  82. mlrun/model_monitoring/applications/results.py +99 -0
  83. mlrun/model_monitoring/controller.py +3 -1
  84. mlrun/model_monitoring/db/__init__.py +2 -0
  85. mlrun/model_monitoring/db/stores/__init__.py +0 -2
  86. mlrun/model_monitoring/db/stores/base/store.py +22 -37
  87. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +43 -21
  88. mlrun/model_monitoring/db/stores/sqldb/models/base.py +39 -8
  89. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +27 -7
  90. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +5 -0
  91. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +246 -224
  92. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +232 -216
  93. mlrun/model_monitoring/db/tsdb/__init__.py +100 -0
  94. mlrun/model_monitoring/db/tsdb/base.py +329 -0
  95. mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
  96. mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
  97. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +240 -0
  98. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +45 -0
  99. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +397 -0
  100. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  101. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  102. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +636 -0
  103. mlrun/model_monitoring/evidently_application.py +6 -118
  104. mlrun/model_monitoring/helpers.py +46 -1
  105. mlrun/model_monitoring/model_endpoint.py +3 -2
  106. mlrun/model_monitoring/stream_processing.py +57 -216
  107. mlrun/model_monitoring/writer.py +134 -124
  108. mlrun/package/utils/_formatter.py +2 -2
  109. mlrun/platforms/__init__.py +10 -9
  110. mlrun/platforms/iguazio.py +21 -202
  111. mlrun/projects/operations.py +19 -12
  112. mlrun/projects/pipelines.py +79 -102
  113. mlrun/projects/project.py +265 -103
  114. mlrun/render.py +15 -14
  115. mlrun/run.py +16 -46
  116. mlrun/runtimes/__init__.py +6 -3
  117. mlrun/runtimes/base.py +8 -7
  118. mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
  119. mlrun/runtimes/funcdoc.py +0 -28
  120. mlrun/runtimes/kubejob.py +2 -1
  121. mlrun/runtimes/local.py +5 -2
  122. mlrun/runtimes/mpijob/__init__.py +0 -20
  123. mlrun/runtimes/mpijob/v1.py +1 -1
  124. mlrun/runtimes/nuclio/api_gateway.py +194 -84
  125. mlrun/runtimes/nuclio/application/application.py +170 -8
  126. mlrun/runtimes/nuclio/function.py +39 -49
  127. mlrun/runtimes/pod.py +16 -36
  128. mlrun/runtimes/remotesparkjob.py +9 -3
  129. mlrun/runtimes/sparkjob/spark3job.py +1 -1
  130. mlrun/runtimes/utils.py +6 -45
  131. mlrun/serving/server.py +2 -1
  132. mlrun/serving/v2_serving.py +5 -1
  133. mlrun/track/tracker.py +2 -1
  134. mlrun/utils/async_http.py +25 -5
  135. mlrun/utils/helpers.py +107 -75
  136. mlrun/utils/logger.py +39 -7
  137. mlrun/utils/notifications/notification/__init__.py +14 -9
  138. mlrun/utils/notifications/notification/base.py +1 -1
  139. mlrun/utils/notifications/notification/slack.py +34 -7
  140. mlrun/utils/notifications/notification/webhook.py +1 -1
  141. mlrun/utils/notifications/notification_pusher.py +147 -16
  142. mlrun/utils/regex.py +9 -0
  143. mlrun/utils/v3io_clients.py +0 -1
  144. mlrun/utils/version/version.json +2 -2
  145. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/METADATA +14 -6
  146. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/RECORD +150 -130
  147. mlrun/kfpops.py +0 -865
  148. mlrun/platforms/other.py +0 -305
  149. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/LICENSE +0 -0
  150. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/WHEEL +0 -0
  151. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/entry_points.txt +0 -0
  152. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/top_level.txt +0 -0
@@ -17,31 +17,30 @@ from typing import Optional, Union
17
17
  from urllib.parse import urljoin
18
18
 
19
19
  import requests
20
- from requests.auth import HTTPBasicAuth
20
+ from nuclio.auth import AuthInfo as NuclioAuthInfo
21
+ from nuclio.auth import AuthKinds as NuclioAuthKinds
21
22
 
22
23
  import mlrun
23
- import mlrun.common.schemas
24
+ import mlrun.common.constants as mlrun_constants
25
+ import mlrun.common.schemas as schemas
26
+ import mlrun.common.types
27
+ from mlrun.model import ModelObj
28
+ from mlrun.platforms.iguazio import min_iguazio_versions
29
+ from mlrun.utils import logger
24
30
 
25
- from ...model import ModelObj
26
- from ..utils import logger
27
- from .function import RemoteRuntime, get_fullname, min_nuclio_versions
28
- from .serving import ServingRuntime
31
+ from .function import min_nuclio_versions
29
32
 
30
- NUCLIO_API_GATEWAY_AUTHENTICATION_MODE_BASIC_AUTH = "basicAuth"
31
- NUCLIO_API_GATEWAY_AUTHENTICATION_MODE_NONE = "none"
32
- PROJECT_NAME_LABEL = "nuclio.io/project-name"
33
33
 
34
-
35
- class APIGatewayAuthenticator(typing.Protocol):
34
+ class Authenticator(typing.Protocol):
36
35
  @property
37
36
  def authentication_mode(self) -> str:
38
- return NUCLIO_API_GATEWAY_AUTHENTICATION_MODE_NONE
37
+ return schemas.APIGatewayAuthenticationMode.none.value
39
38
 
40
39
  @classmethod
41
- def from_scheme(cls, api_gateway_spec: mlrun.common.schemas.APIGatewaySpec):
40
+ def from_scheme(cls, api_gateway_spec: schemas.APIGatewaySpec):
42
41
  if (
43
42
  api_gateway_spec.authenticationMode
44
- == NUCLIO_API_GATEWAY_AUTHENTICATION_MODE_BASIC_AUTH
43
+ == schemas.APIGatewayAuthenticationMode.basic.value
45
44
  ):
46
45
  if api_gateway_spec.authentication:
47
46
  return BasicAuth(
@@ -50,15 +49,24 @@ class APIGatewayAuthenticator(typing.Protocol):
50
49
  )
51
50
  else:
52
51
  return BasicAuth()
52
+ elif (
53
+ api_gateway_spec.authenticationMode
54
+ == schemas.APIGatewayAuthenticationMode.access_key.value
55
+ ):
56
+ return AccessKeyAuth()
53
57
  else:
54
58
  return NoneAuth()
55
59
 
56
60
  def to_scheme(
57
61
  self,
58
- ) -> Optional[dict[str, Optional[mlrun.common.schemas.APIGatewayBasicAuth]]]:
62
+ ) -> Optional[dict[str, Optional[schemas.APIGatewayBasicAuth]]]:
59
63
  return None
60
64
 
61
65
 
66
+ class APIGatewayAuthenticator(Authenticator, ModelObj):
67
+ _dict_fields = ["authentication_mode"]
68
+
69
+
62
70
  class NoneAuth(APIGatewayAuthenticator):
63
71
  """
64
72
  An API gateway authenticator with no authentication.
@@ -81,18 +89,28 @@ class BasicAuth(APIGatewayAuthenticator):
81
89
 
82
90
  @property
83
91
  def authentication_mode(self) -> str:
84
- return NUCLIO_API_GATEWAY_AUTHENTICATION_MODE_BASIC_AUTH
92
+ return schemas.APIGatewayAuthenticationMode.basic.value
85
93
 
86
94
  def to_scheme(
87
95
  self,
88
- ) -> Optional[dict[str, Optional[mlrun.common.schemas.APIGatewayBasicAuth]]]:
96
+ ) -> Optional[dict[str, Optional[schemas.APIGatewayBasicAuth]]]:
89
97
  return {
90
- "basicAuth": mlrun.common.schemas.APIGatewayBasicAuth(
98
+ "basicAuth": schemas.APIGatewayBasicAuth(
91
99
  username=self._username, password=self._password
92
100
  )
93
101
  }
94
102
 
95
103
 
104
+ class AccessKeyAuth(APIGatewayAuthenticator):
105
+ """
106
+ An API gateway authenticator with access key authentication.
107
+ """
108
+
109
+ @property
110
+ def authentication_mode(self) -> str:
111
+ return schemas.APIGatewayAuthenticationMode.access_key.value
112
+
113
+
96
114
  class APIGatewayMetadata(ModelObj):
97
115
  _dict_fields = ["name", "namespace", "labels", "annotations", "creation_timestamp"]
98
116
 
@@ -138,17 +156,17 @@ class APIGatewaySpec(ModelObj):
138
156
  def __init__(
139
157
  self,
140
158
  functions: Union[
141
- list[str],
142
- Union[
143
- list[
144
- Union[
145
- RemoteRuntime,
146
- ServingRuntime,
147
- ]
148
- ],
149
- RemoteRuntime,
150
- ServingRuntime,
159
+ list[
160
+ Union[
161
+ str,
162
+ "mlrun.runtimes.nuclio.function.RemoteRuntime",
163
+ "mlrun.runtimes.nuclio.serving.ServingRuntime",
164
+ "mlrun.runtimes.nuclio.application.ApplicationRuntime",
165
+ ]
151
166
  ],
167
+ "mlrun.runtimes.nuclio.function.RemoteRuntime",
168
+ "mlrun.runtimes.nuclio.serving.ServingRuntime",
169
+ "mlrun.runtimes.nuclio.application.ApplicationRuntime",
152
170
  ],
153
171
  project: str = None,
154
172
  description: str = "",
@@ -156,20 +174,24 @@ class APIGatewaySpec(ModelObj):
156
174
  path: str = "/",
157
175
  authentication: Optional[APIGatewayAuthenticator] = NoneAuth(),
158
176
  canary: Optional[list[int]] = None,
177
+ ports: Optional[list[int]] = None,
159
178
  ):
160
179
  """
161
180
  :param functions: The list of functions associated with the API gateway
162
181
  Can be a list of function names (["my-func1", "my-func2"])
163
182
  or a list or a single entity of
164
183
  :py:class:`~mlrun.runtimes.nuclio.function.RemoteRuntime` OR
165
- :py:class:`~mlrun.runtimes.nuclio.serving.ServingRuntime`
184
+ :py:class:`~mlrun.runtimes.nuclio.serving.ServingRuntime` OR
185
+ :py:class:`~mlrun.runtimes.nuclio.application.ApplicationRuntime`
166
186
  :param project: The project name
167
187
  :param description: Optional description of the API gateway
168
188
  :param path: Optional path of the API gateway, default value is "/"
169
189
  :param authentication: The authentication for the API gateway of type
170
190
  :py:class:`~mlrun.runtimes.nuclio.api_gateway.BasicAuth`
171
191
  :param host: The host of the API gateway (optional). If not set, it will be automatically generated
172
- :param canary: The canary percents for the API gateway of type list[int]; for instance: [20,80]
192
+ :param canary: The canary percents for the API gateway of type list[int]; for instance: [20,80] (optional)
193
+ :param ports: The ports of the API gateway, as a list of integers that correspond to the functions in the
194
+ functions list. for instance: [8050] or [8050, 8081] (optional)
173
195
  """
174
196
  self.description = description
175
197
  self.host = host
@@ -178,26 +200,28 @@ class APIGatewaySpec(ModelObj):
178
200
  self.functions = functions
179
201
  self.canary = canary
180
202
  self.project = project
203
+ self.ports = ports
181
204
 
182
- self.validate(project=project, functions=functions, canary=canary)
205
+ self.validate(project=project, functions=functions, canary=canary, ports=ports)
183
206
 
184
207
  def validate(
185
208
  self,
186
209
  project: str,
187
210
  functions: Union[
188
- list[str],
189
- Union[
190
- list[
191
- Union[
192
- RemoteRuntime,
193
- ServingRuntime,
194
- ]
195
- ],
196
- RemoteRuntime,
197
- ServingRuntime,
211
+ list[
212
+ Union[
213
+ str,
214
+ "mlrun.runtimes.nuclio.function.RemoteRuntime",
215
+ "mlrun.runtimes.nuclio.serving.ServingRuntime",
216
+ "mlrun.runtimes.nuclio.application.ApplicationRuntime",
217
+ ]
198
218
  ],
219
+ "mlrun.runtimes.nuclio.function.RemoteRuntime",
220
+ "mlrun.runtimes.nuclio.serving.ServingRuntime",
221
+ "mlrun.runtimes.nuclio.application.ApplicationRuntime",
199
222
  ],
200
223
  canary: Optional[list[int]] = None,
224
+ ports: Optional[list[int]] = None,
201
225
  ):
202
226
  self.functions = self._validate_functions(project=project, functions=functions)
203
227
 
@@ -205,6 +229,10 @@ class APIGatewaySpec(ModelObj):
205
229
  if canary:
206
230
  self.canary = self._validate_canary(canary)
207
231
 
232
+ # validating ports
233
+ if ports:
234
+ self.ports = self._validate_ports(ports)
235
+
208
236
  def _validate_canary(self, canary: list[int]):
209
237
  if len(self.functions) != len(canary):
210
238
  raise mlrun.errors.MLRunInvalidArgumentError(
@@ -221,20 +249,29 @@ class APIGatewaySpec(ModelObj):
221
249
  )
222
250
  return canary
223
251
 
252
+ def _validate_ports(self, ports):
253
+ if len(self.functions) != len(ports):
254
+ raise mlrun.errors.MLRunInvalidArgumentError(
255
+ "Function and port lists lengths do not match"
256
+ )
257
+
258
+ return ports
259
+
224
260
  @staticmethod
225
261
  def _validate_functions(
226
262
  project: str,
227
263
  functions: Union[
228
- list[str],
229
- Union[
230
- list[
231
- Union[
232
- RemoteRuntime,
233
- ServingRuntime,
234
- ]
235
- ],
236
- Union[RemoteRuntime, ServingRuntime],
264
+ list[
265
+ Union[
266
+ str,
267
+ "mlrun.runtimes.nuclio.function.RemoteRuntime",
268
+ "mlrun.runtimes.nuclio.serving.ServingRuntime",
269
+ "mlrun.runtimes.nuclio.application.ApplicationRuntime",
270
+ ]
237
271
  ],
272
+ "mlrun.runtimes.nuclio.function.RemoteRuntime",
273
+ "mlrun.runtimes.nuclio.serving.ServingRuntime",
274
+ "mlrun.runtimes.nuclio.application.ApplicationRuntime",
238
275
  ],
239
276
  ):
240
277
  if not isinstance(functions, list):
@@ -250,7 +287,21 @@ class APIGatewaySpec(ModelObj):
250
287
  function_names = []
251
288
  for func in functions:
252
289
  if isinstance(func, str):
253
- function_names.append(func)
290
+ # check whether the function was passed as a URI or just a name
291
+ parsed_project, function_name, _, _ = (
292
+ mlrun.common.helpers.parse_versioned_object_uri(func)
293
+ )
294
+
295
+ if parsed_project and function_name:
296
+ # check that parsed project and passed project are the same
297
+ if parsed_project != project:
298
+ raise mlrun.errors.MLRunInvalidArgumentError(
299
+ "Function doesn't belong to passed project"
300
+ )
301
+ function_uri = func
302
+ else:
303
+ function_uri = mlrun.utils.generate_object_uri(project, func)
304
+ function_names.append(function_uri)
254
305
  continue
255
306
 
256
307
  function_name = (
@@ -265,8 +316,13 @@ class APIGatewaySpec(ModelObj):
265
316
  f"input function {function_name} "
266
317
  f"does not belong to this project"
267
318
  )
268
- nuclio_name = get_fullname(function_name, project, func.metadata.tag)
269
- function_names.append(nuclio_name)
319
+ function_uri = mlrun.utils.generate_object_uri(
320
+ project,
321
+ function_name,
322
+ func.metadata.tag,
323
+ func.metadata.hash,
324
+ )
325
+ function_names.append(function_uri)
270
326
  return function_names
271
327
 
272
328
 
@@ -312,8 +368,9 @@ class APIGateway(ModelObj):
312
368
  def invoke(
313
369
  self,
314
370
  method="POST",
315
- headers: dict = {},
316
- auth: Optional[tuple[str, str]] = None,
371
+ headers: dict = None,
372
+ credentials: Optional[tuple[str, str]] = None,
373
+ path: Optional[str] = None,
317
374
  **kwargs,
318
375
  ):
319
376
  """
@@ -321,7 +378,9 @@ class APIGateway(ModelObj):
321
378
 
322
379
  :param method: (str, optional) The HTTP method for the invocation.
323
380
  :param headers: (dict, optional) The HTTP headers for the invocation.
324
- :param auth: (Optional[tuple[str, str]], optional) The authentication creds for the invocation if required.
381
+ :param credentials: (Optional[tuple[str, str]], optional) The (username,password) for the invocation if required
382
+ can also be set by the environment variable (_, V3IO_ACCESS_KEY) for access key authentication.
383
+ :param path: (str, optional) The sub-path for the invocation.
325
384
  :param kwargs: (dict) Additional keyword arguments.
326
385
 
327
386
  :return: The response from the API gateway invocation.
@@ -338,20 +397,44 @@ class APIGateway(ModelObj):
338
397
  f"API gateway is not ready. " f"Current state: {self.state}"
339
398
  )
340
399
 
400
+ auth = None
401
+
341
402
  if (
342
403
  self.spec.authentication.authentication_mode
343
- == NUCLIO_API_GATEWAY_AUTHENTICATION_MODE_BASIC_AUTH
344
- and not auth
404
+ == schemas.APIGatewayAuthenticationMode.basic.value
345
405
  ):
346
- raise mlrun.errors.MLRunInvalidArgumentError(
347
- "API Gateway invocation requires authentication. Please pass credentials"
348
- )
406
+ if not credentials:
407
+ raise mlrun.errors.MLRunInvalidArgumentError(
408
+ "API Gateway invocation requires authentication. Please pass credentials"
409
+ )
410
+ auth = NuclioAuthInfo(
411
+ username=credentials[0], password=credentials[1]
412
+ ).to_requests_auth()
413
+
414
+ if (
415
+ self.spec.authentication.authentication_mode
416
+ == schemas.APIGatewayAuthenticationMode.access_key.value
417
+ ):
418
+ # inject access key from env
419
+ if credentials:
420
+ auth = NuclioAuthInfo(
421
+ username=credentials[0],
422
+ password=credentials[1],
423
+ mode=NuclioAuthKinds.iguazio,
424
+ ).to_requests_auth()
425
+ else:
426
+ auth = NuclioAuthInfo().from_envvar().to_requests_auth()
427
+ if not auth:
428
+ raise mlrun.errors.MLRunInvalidArgumentError(
429
+ "API Gateway invocation requires authentication. Please set V3IO_ACCESS_KEY env var"
430
+ )
431
+ url = urljoin(self.invoke_url, path or "")
349
432
  return requests.request(
350
433
  method=method,
351
- url=self.invoke_url,
352
- headers=headers,
434
+ url=url,
435
+ headers=headers or {},
436
+ auth=auth,
353
437
  **kwargs,
354
- auth=HTTPBasicAuth(*auth) if auth else None,
355
438
  )
356
439
 
357
440
  def wait_for_readiness(self, max_wait_time=90):
@@ -376,10 +459,10 @@ class APIGateway(ModelObj):
376
459
  )
377
460
 
378
461
  def is_ready(self):
379
- if self.state is not mlrun.common.schemas.api_gateway.APIGatewayState.ready:
462
+ if self.state is not schemas.api_gateway.APIGatewayState.ready:
380
463
  # try to sync the state
381
464
  self.sync()
382
- return self.state == mlrun.common.schemas.api_gateway.APIGatewayState.ready
465
+ return self.state == schemas.api_gateway.APIGatewayState.ready
383
466
 
384
467
  def sync(self):
385
468
  """
@@ -407,16 +490,27 @@ class APIGateway(ModelObj):
407
490
  """
408
491
  self.spec.authentication = BasicAuth(username=username, password=password)
409
492
 
493
+ @min_iguazio_versions("3.5.5")
494
+ def with_access_key_auth(self):
495
+ """
496
+ Set access key authentication for the API gateway.
497
+ """
498
+ self.spec.authentication = AccessKeyAuth()
499
+
410
500
  def with_canary(
411
501
  self,
412
502
  functions: Union[
413
- list[str],
414
503
  list[
415
504
  Union[
416
- RemoteRuntime,
417
- ServingRuntime,
505
+ str,
506
+ "mlrun.runtimes.nuclio.function.RemoteRuntime",
507
+ "mlrun.runtimes.nuclio.serving.ServingRuntime",
508
+ "mlrun.runtimes.nuclio.application.ApplicationRuntime",
418
509
  ]
419
510
  ],
511
+ "mlrun.runtimes.nuclio.function.RemoteRuntime",
512
+ "mlrun.runtimes.nuclio.serving.ServingRuntime",
513
+ "mlrun.runtimes.nuclio.application.ApplicationRuntime",
420
514
  ],
421
515
  canary: list[int],
422
516
  ):
@@ -427,7 +521,8 @@ class APIGateway(ModelObj):
427
521
  Can be a list of function names (["my-func1", "my-func2"])
428
522
  or a list of nuclio functions of types
429
523
  :py:class:`~mlrun.runtimes.nuclio.function.RemoteRuntime` OR
430
- :py:class:`~mlrun.runtimes.nuclio.serving.ServingRuntime`
524
+ :py:class:`~mlrun.runtimes.nuclio.serving.ServingRuntime` OR
525
+ :py:class:`~mlrun.runtimes.nuclio.application.ApplicationRuntime`
431
526
  :param canary: The canary percents for the API gateway of type list[int]; for instance: [20,80]
432
527
 
433
528
  """
@@ -440,14 +535,27 @@ class APIGateway(ModelObj):
440
535
  project=self.spec.project, functions=functions, canary=canary
441
536
  )
442
537
 
538
+ def with_ports(self, ports: list[int]):
539
+ """
540
+ Set ports for the API gateway
541
+
542
+ :param ports: The ports of the API gateway, as a list of integers that correspond to the functions in the
543
+ functions list. for instance: [8050] or [8050, 8081]
544
+ """
545
+ self.spec.validate(
546
+ project=self.spec.project, functions=self.spec.functions, ports=ports
547
+ )
548
+
443
549
  @classmethod
444
- def from_scheme(cls, api_gateway: mlrun.common.schemas.APIGateway):
445
- project = api_gateway.metadata.labels.get(PROJECT_NAME_LABEL)
550
+ def from_scheme(cls, api_gateway: schemas.APIGateway):
551
+ project = api_gateway.metadata.labels.get(
552
+ mlrun_constants.MLRunInternalLabels.nuclio_project_name
553
+ )
446
554
  functions, canary = cls._resolve_canary(api_gateway.spec.upstreams)
447
555
  state = (
448
556
  api_gateway.status.state
449
557
  if api_gateway.status
450
- else mlrun.common.schemas.APIGatewayState.none
558
+ else schemas.APIGatewayState.none
451
559
  )
452
560
  new_api_gateway = cls(
453
561
  metadata=APIGatewayMetadata(
@@ -466,14 +574,14 @@ class APIGateway(ModelObj):
466
574
  new_api_gateway.state = state
467
575
  return new_api_gateway
468
576
 
469
- def to_scheme(self) -> mlrun.common.schemas.APIGateway:
577
+ def to_scheme(self) -> schemas.APIGateway:
470
578
  upstreams = (
471
579
  [
472
- mlrun.common.schemas.APIGatewayUpstream(
580
+ schemas.APIGatewayUpstream(
473
581
  nucliofunction={"name": self.spec.functions[0]},
474
582
  percentage=self.spec.canary[0],
475
583
  ),
476
- mlrun.common.schemas.APIGatewayUpstream(
584
+ schemas.APIGatewayUpstream(
477
585
  # do not set percent for the second function,
478
586
  # so we can define which function to display as a primary one in UI
479
587
  nucliofunction={"name": self.spec.functions[1]},
@@ -481,22 +589,24 @@ class APIGateway(ModelObj):
481
589
  ]
482
590
  if self.spec.canary
483
591
  else [
484
- mlrun.common.schemas.APIGatewayUpstream(
592
+ schemas.APIGatewayUpstream(
485
593
  nucliofunction={"name": function_name},
486
594
  )
487
595
  for function_name in self.spec.functions
488
596
  ]
489
597
  )
490
- api_gateway = mlrun.common.schemas.APIGateway(
491
- metadata=mlrun.common.schemas.APIGatewayMetadata(
492
- name=self.metadata.name, labels={}
493
- ),
494
- spec=mlrun.common.schemas.APIGatewaySpec(
598
+ if self.spec.ports:
599
+ for i, port in enumerate(self.spec.ports):
600
+ upstreams[i].port = port
601
+
602
+ api_gateway = schemas.APIGateway(
603
+ metadata=schemas.APIGatewayMetadata(name=self.metadata.name, labels={}),
604
+ spec=schemas.APIGatewaySpec(
495
605
  name=self.metadata.name,
496
606
  description=self.spec.description,
497
607
  host=self.spec.host,
498
608
  path=self.spec.path,
499
- authenticationMode=mlrun.common.schemas.APIGatewayAuthenticationMode.from_str(
609
+ authenticationMode=schemas.APIGatewayAuthenticationMode.from_str(
500
610
  self.spec.authentication.authentication_mode
501
611
  ),
502
612
  upstreams=upstreams,
@@ -526,7 +636,7 @@ class APIGateway(ModelObj):
526
636
 
527
637
  @staticmethod
528
638
  def _resolve_canary(
529
- upstreams: list[mlrun.common.schemas.APIGatewayUpstream],
639
+ upstreams: list[schemas.APIGatewayUpstream],
530
640
  ) -> tuple[Union[list[str], None], Union[list[int], None]]:
531
641
  if len(upstreams) == 1:
532
642
  return [upstreams[0].nucliofunction.get("name")], None