mlrun 1.7.0rc20__py3-none-any.whl → 1.7.0rc28__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 (92) hide show
  1. mlrun/__main__.py +10 -8
  2. mlrun/alerts/alert.py +55 -18
  3. mlrun/api/schemas/__init__.py +3 -3
  4. mlrun/artifacts/manager.py +26 -0
  5. mlrun/common/constants.py +3 -2
  6. mlrun/common/formatters/__init__.py +1 -0
  7. mlrun/common/formatters/artifact.py +26 -3
  8. mlrun/common/formatters/base.py +44 -9
  9. mlrun/common/formatters/function.py +12 -7
  10. mlrun/common/formatters/run.py +26 -0
  11. mlrun/common/helpers.py +11 -0
  12. mlrun/common/schemas/__init__.py +4 -0
  13. mlrun/common/schemas/alert.py +5 -9
  14. mlrun/common/schemas/api_gateway.py +64 -16
  15. mlrun/common/schemas/artifact.py +11 -0
  16. mlrun/common/schemas/constants.py +3 -0
  17. mlrun/common/schemas/feature_store.py +58 -28
  18. mlrun/common/schemas/model_monitoring/constants.py +21 -12
  19. mlrun/common/schemas/model_monitoring/model_endpoints.py +0 -12
  20. mlrun/common/schemas/pipeline.py +16 -0
  21. mlrun/common/schemas/project.py +17 -0
  22. mlrun/common/schemas/runs.py +17 -0
  23. mlrun/common/schemas/schedule.py +1 -1
  24. mlrun/common/types.py +6 -0
  25. mlrun/config.py +17 -25
  26. mlrun/datastore/azure_blob.py +2 -1
  27. mlrun/datastore/datastore.py +3 -3
  28. mlrun/datastore/google_cloud_storage.py +6 -2
  29. mlrun/datastore/snowflake_utils.py +3 -1
  30. mlrun/datastore/sources.py +26 -11
  31. mlrun/datastore/store_resources.py +2 -0
  32. mlrun/datastore/targets.py +68 -16
  33. mlrun/db/base.py +83 -2
  34. mlrun/db/httpdb.py +280 -63
  35. mlrun/db/nopdb.py +60 -3
  36. mlrun/errors.py +5 -3
  37. mlrun/execution.py +28 -13
  38. mlrun/feature_store/feature_vector.py +8 -0
  39. mlrun/feature_store/retrieval/spark_merger.py +13 -2
  40. mlrun/launcher/local.py +4 -0
  41. mlrun/launcher/remote.py +1 -0
  42. mlrun/model.py +32 -3
  43. mlrun/model_monitoring/api.py +7 -52
  44. mlrun/model_monitoring/applications/base.py +5 -7
  45. mlrun/model_monitoring/applications/histogram_data_drift.py +1 -1
  46. mlrun/model_monitoring/db/stores/__init__.py +37 -24
  47. mlrun/model_monitoring/db/stores/base/store.py +40 -1
  48. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +42 -87
  49. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +27 -35
  50. mlrun/model_monitoring/db/tsdb/__init__.py +15 -15
  51. mlrun/model_monitoring/db/tsdb/base.py +1 -14
  52. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +22 -18
  53. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +86 -56
  54. mlrun/model_monitoring/helpers.py +34 -9
  55. mlrun/model_monitoring/stream_processing.py +12 -11
  56. mlrun/model_monitoring/writer.py +11 -11
  57. mlrun/projects/operations.py +5 -0
  58. mlrun/projects/pipelines.py +35 -21
  59. mlrun/projects/project.py +216 -107
  60. mlrun/render.py +10 -5
  61. mlrun/run.py +15 -5
  62. mlrun/runtimes/__init__.py +2 -0
  63. mlrun/runtimes/base.py +17 -4
  64. mlrun/runtimes/daskjob.py +8 -1
  65. mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
  66. mlrun/runtimes/local.py +23 -4
  67. mlrun/runtimes/nuclio/application/application.py +0 -2
  68. mlrun/runtimes/nuclio/function.py +31 -2
  69. mlrun/runtimes/nuclio/serving.py +9 -6
  70. mlrun/runtimes/pod.py +5 -29
  71. mlrun/runtimes/remotesparkjob.py +8 -2
  72. mlrun/serving/__init__.py +8 -1
  73. mlrun/serving/routers.py +75 -59
  74. mlrun/serving/server.py +11 -0
  75. mlrun/serving/states.py +80 -8
  76. mlrun/serving/utils.py +19 -11
  77. mlrun/serving/v2_serving.py +66 -39
  78. mlrun/utils/helpers.py +91 -11
  79. mlrun/utils/logger.py +36 -2
  80. mlrun/utils/notifications/notification/base.py +43 -7
  81. mlrun/utils/notifications/notification/git.py +21 -0
  82. mlrun/utils/notifications/notification/slack.py +9 -14
  83. mlrun/utils/notifications/notification/webhook.py +41 -1
  84. mlrun/utils/notifications/notification_pusher.py +3 -9
  85. mlrun/utils/regex.py +9 -0
  86. mlrun/utils/version/version.json +2 -2
  87. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/METADATA +16 -9
  88. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/RECORD +92 -91
  89. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/WHEEL +1 -1
  90. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/LICENSE +0 -0
  91. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/entry_points.txt +0 -0
  92. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,7 @@
14
14
  #
15
15
  from typing import Optional
16
16
 
17
- from pydantic import BaseModel, Extra, Field
17
+ import pydantic
18
18
 
19
19
  from .auth import AuthorizationResourceTypes, Credentials
20
20
  from .object import (
@@ -27,32 +27,42 @@ from .object import (
27
27
  )
28
28
 
29
29
 
30
- class Feature(BaseModel):
30
+ class FeatureStoreBaseModel(pydantic.BaseModel):
31
+ """
32
+ Intermediate base class, in order to override pydantic's configuration, as per
33
+ https://docs.pydantic.dev/1.10/usage/model_config/#change-behaviour-globally
34
+ """
35
+
36
+ class Config:
37
+ copy_on_model_validation = "none"
38
+
39
+
40
+ class Feature(FeatureStoreBaseModel):
31
41
  name: str
32
42
  value_type: str
33
43
  labels: Optional[dict] = {}
34
44
 
35
45
  class Config:
36
- extra = Extra.allow
46
+ extra = pydantic.Extra.allow
37
47
 
38
48
 
39
- class Entity(BaseModel):
49
+ class Entity(FeatureStoreBaseModel):
40
50
  name: str
41
51
  value_type: str
42
52
  labels: Optional[dict] = {}
43
53
 
44
54
  class Config:
45
- extra = Extra.allow
55
+ extra = pydantic.Extra.allow
46
56
 
47
57
 
48
58
  class FeatureSetSpec(ObjectSpec):
49
59
  entities: list[Entity] = []
50
60
  features: list[Feature] = []
51
- engine: Optional[str] = Field(default="storey")
61
+ engine: Optional[str] = pydantic.Field(default="storey")
52
62
 
53
63
 
54
- class FeatureSet(BaseModel):
55
- kind: ObjectKind = Field(ObjectKind.feature_set, const=True)
64
+ class FeatureSet(FeatureStoreBaseModel):
65
+ kind: ObjectKind = pydantic.Field(ObjectKind.feature_set, const=True)
56
66
  metadata: ObjectMetadata
57
67
  spec: FeatureSetSpec
58
68
  status: ObjectStatus
@@ -62,7 +72,7 @@ class FeatureSet(BaseModel):
62
72
  return AuthorizationResourceTypes.feature_set
63
73
 
64
74
 
65
- class EntityRecord(BaseModel):
75
+ class EntityRecord(FeatureStoreBaseModel):
66
76
  name: str
67
77
  value_type: str
68
78
  labels: list[LabelRecord]
@@ -71,7 +81,7 @@ class EntityRecord(BaseModel):
71
81
  orm_mode = True
72
82
 
73
83
 
74
- class FeatureRecord(BaseModel):
84
+ class FeatureRecord(FeatureStoreBaseModel):
75
85
  name: str
76
86
  value_type: str
77
87
  labels: list[LabelRecord]
@@ -88,44 +98,64 @@ class FeatureSetRecord(ObjectRecord):
88
98
  orm_mode = True
89
99
 
90
100
 
91
- class FeatureSetsOutput(BaseModel):
101
+ class FeatureSetsOutput(FeatureStoreBaseModel):
92
102
  feature_sets: list[FeatureSet]
93
103
 
94
104
 
95
- class FeatureSetsTagsOutput(BaseModel):
105
+ class FeatureSetsTagsOutput(FeatureStoreBaseModel):
96
106
  tags: list[str] = []
97
107
 
98
108
 
99
- class FeatureSetDigestSpec(BaseModel):
109
+ class FeatureSetDigestSpec(FeatureStoreBaseModel):
100
110
  entities: list[Entity]
101
111
  features: list[Feature]
102
112
 
103
113
 
104
- class FeatureSetDigestOutput(BaseModel):
114
+ class FeatureSetDigestOutput(FeatureStoreBaseModel):
105
115
  metadata: ObjectMetadata
106
116
  spec: FeatureSetDigestSpec
107
117
 
108
118
 
109
- class FeatureListOutput(BaseModel):
119
+ class FeatureSetDigestSpecV2(FeatureStoreBaseModel):
120
+ entities: list[Entity]
121
+
122
+
123
+ class FeatureSetDigestOutputV2(FeatureStoreBaseModel):
124
+ feature_set_index: int
125
+ metadata: ObjectMetadata
126
+ spec: FeatureSetDigestSpecV2
127
+
128
+
129
+ class FeatureListOutput(FeatureStoreBaseModel):
110
130
  feature: Feature
111
131
  feature_set_digest: FeatureSetDigestOutput
112
132
 
113
133
 
114
- class FeaturesOutput(BaseModel):
134
+ class FeaturesOutput(FeatureStoreBaseModel):
115
135
  features: list[FeatureListOutput]
116
136
 
117
137
 
118
- class EntityListOutput(BaseModel):
138
+ class FeaturesOutputV2(FeatureStoreBaseModel):
139
+ features: list[Feature]
140
+ feature_set_digests: list[FeatureSetDigestOutputV2]
141
+
142
+
143
+ class EntityListOutput(FeatureStoreBaseModel):
119
144
  entity: Entity
120
145
  feature_set_digest: FeatureSetDigestOutput
121
146
 
122
147
 
123
- class EntitiesOutput(BaseModel):
148
+ class EntitiesOutputV2(FeatureStoreBaseModel):
149
+ entities: list[Entity]
150
+ feature_set_digests: list[FeatureSetDigestOutputV2]
151
+
152
+
153
+ class EntitiesOutput(FeatureStoreBaseModel):
124
154
  entities: list[EntityListOutput]
125
155
 
126
156
 
127
- class FeatureVector(BaseModel):
128
- kind: ObjectKind = Field(ObjectKind.feature_vector, const=True)
157
+ class FeatureVector(FeatureStoreBaseModel):
158
+ kind: ObjectKind = pydantic.Field(ObjectKind.feature_vector, const=True)
129
159
  metadata: ObjectMetadata
130
160
  spec: ObjectSpec
131
161
  status: ObjectStatus
@@ -139,39 +169,39 @@ class FeatureVectorRecord(ObjectRecord):
139
169
  pass
140
170
 
141
171
 
142
- class FeatureVectorsOutput(BaseModel):
172
+ class FeatureVectorsOutput(FeatureStoreBaseModel):
143
173
  feature_vectors: list[FeatureVector]
144
174
 
145
175
 
146
- class FeatureVectorsTagsOutput(BaseModel):
176
+ class FeatureVectorsTagsOutput(FeatureStoreBaseModel):
147
177
  tags: list[str] = []
148
178
 
149
179
 
150
- class DataSource(BaseModel):
180
+ class DataSource(FeatureStoreBaseModel):
151
181
  kind: str
152
182
  name: str
153
183
  path: str
154
184
 
155
185
  class Config:
156
- extra = Extra.allow
186
+ extra = pydantic.Extra.allow
157
187
 
158
188
 
159
- class DataTarget(BaseModel):
189
+ class DataTarget(FeatureStoreBaseModel):
160
190
  kind: str
161
191
  name: str
162
192
  path: Optional[str]
163
193
 
164
194
  class Config:
165
- extra = Extra.allow
195
+ extra = pydantic.Extra.allow
166
196
 
167
197
 
168
- class FeatureSetIngestInput(BaseModel):
198
+ class FeatureSetIngestInput(FeatureStoreBaseModel):
169
199
  source: Optional[DataSource]
170
200
  targets: Optional[list[DataTarget]]
171
201
  infer_options: Optional[int]
172
202
  credentials: Credentials = Credentials()
173
203
 
174
204
 
175
- class FeatureSetIngestOutput(BaseModel):
205
+ class FeatureSetIngestOutput(FeatureStoreBaseModel):
176
206
  feature_set: FeatureSet
177
207
  run_object: dict
@@ -78,8 +78,6 @@ class EventFieldType:
78
78
  FEATURE_SET_URI = "monitoring_feature_set_uri"
79
79
  ALGORITHM = "algorithm"
80
80
  VALUE = "value"
81
- DRIFT_DETECTED_THRESHOLD = "drift_detected_threshold"
82
- POSSIBLE_DRIFT_THRESHOLD = "possible_drift_threshold"
83
81
  SAMPLE_PARQUET_PATH = "sample_parquet_path"
84
82
  TIME = "time"
85
83
  TABLE_COLUMN = "table_column"
@@ -158,19 +156,36 @@ class EventKeyMetrics:
158
156
  REAL_TIME = "real_time"
159
157
 
160
158
 
161
- class ModelEndpointTarget:
159
+ class ModelEndpointTarget(MonitoringStrEnum):
162
160
  V3IO_NOSQL = "v3io-nosql"
163
161
  SQL = "sql"
164
162
 
165
163
 
164
+ class StreamKind(MonitoringStrEnum):
165
+ V3IO_STREAM = "v3io_stream"
166
+ KAFKA = "kafka"
167
+
168
+
169
+ class TSDBTarget(MonitoringStrEnum):
170
+ V3IO_TSDB = "v3io-tsdb"
171
+ TDEngine = "tdengine"
172
+ PROMETHEUS = "prometheus"
173
+
174
+
166
175
  class ProjectSecretKeys:
167
176
  ENDPOINT_STORE_CONNECTION = "MODEL_MONITORING_ENDPOINT_STORE_CONNECTION"
168
177
  ACCESS_KEY = "MODEL_MONITORING_ACCESS_KEY"
169
- PIPELINES_ACCESS_KEY = "MODEL_MONITORING_PIPELINES_ACCESS_KEY"
170
- KAFKA_BROKERS = "KAFKA_BROKERS"
171
178
  STREAM_PATH = "STREAM_PATH"
172
179
  TSDB_CONNECTION = "TSDB_CONNECTION"
173
180
 
181
+ @classmethod
182
+ def mandatory_secrets(cls):
183
+ return [
184
+ cls.ENDPOINT_STORE_CONNECTION,
185
+ cls.STREAM_PATH,
186
+ cls.TSDB_CONNECTION,
187
+ ]
188
+
174
189
 
175
190
  class ModelMonitoringStoreKinds:
176
191
  ENDPOINTS = "endpoints"
@@ -318,7 +333,7 @@ class ResultKindApp(Enum):
318
333
  concept_drift = 1
319
334
  model_performance = 2
320
335
  system_performance = 3
321
- custom = 4
336
+ mm_app_anomaly = 4
322
337
 
323
338
 
324
339
  class ResultStatusApp(IntEnum):
@@ -344,12 +359,6 @@ class ControllerPolicy:
344
359
  BASE_PERIOD = "base_period"
345
360
 
346
361
 
347
- class TSDBTarget:
348
- V3IO_TSDB = "v3io-tsdb"
349
- TDEngine = "tdengine"
350
- PROMETHEUS = "prometheus"
351
-
352
-
353
362
  class HistogramDataDriftApplicationConstants:
354
363
  NAME = "histogram-data-drift"
355
364
  GENERAL_RESULT_NAME = "general_drift"
@@ -103,18 +103,6 @@ class ModelEndpointSpec(ObjectSpec):
103
103
  json_parse_values=json_parse_values,
104
104
  )
105
105
 
106
- @validator("monitor_configuration")
107
- @classmethod
108
- def set_name(cls, monitor_configuration):
109
- return monitor_configuration or {
110
- EventFieldType.DRIFT_DETECTED_THRESHOLD: (
111
- mlrun.mlconf.model_endpoint_monitoring.drift_thresholds.default.drift_detected
112
- ),
113
- EventFieldType.POSSIBLE_DRIFT_THRESHOLD: (
114
- mlrun.mlconf.model_endpoint_monitoring.drift_thresholds.default.possible_drift
115
- ),
116
- }
117
-
118
106
  @validator("model_uri")
119
107
  @classmethod
120
108
  def validate_model_uri(cls, model_uri):
@@ -15,6 +15,22 @@
15
15
  import typing
16
16
 
17
17
  import pydantic
18
+ from deprecated import deprecated
19
+
20
+ import mlrun.common.types
21
+
22
+
23
+ @deprecated(
24
+ version="1.7.0",
25
+ reason="mlrun.common.schemas.PipelinesFormat is deprecated and will be removed in 1.9.0. "
26
+ "Use mlrun.common.formatters.PipelineFormat instead.",
27
+ category=FutureWarning,
28
+ )
29
+ class PipelinesFormat(mlrun.common.types.StrEnum):
30
+ full = "full"
31
+ metadata_only = "metadata_only"
32
+ summary = "summary"
33
+ name_only = "name_only"
18
34
 
19
35
 
20
36
  class PipelinesPagination(str):
@@ -16,6 +16,7 @@ import datetime
16
16
  import typing
17
17
 
18
18
  import pydantic
19
+ from deprecated import deprecated
19
20
 
20
21
  import mlrun.common.types
21
22
 
@@ -23,6 +24,22 @@ from .common import ImageBuilder
23
24
  from .object import ObjectKind, ObjectStatus
24
25
 
25
26
 
27
+ @deprecated(
28
+ version="1.7.0",
29
+ reason="mlrun.common.schemas.ProjectsFormat is deprecated and will be removed in 1.9.0. "
30
+ "Use mlrun.common.formatters.ProjectFormat instead.",
31
+ category=FutureWarning,
32
+ )
33
+ class ProjectsFormat(mlrun.common.types.StrEnum):
34
+ full = "full"
35
+ name_only = "name_only"
36
+ # minimal format removes large fields from the response (e.g. functions, workflows, artifacts)
37
+ # and is used for faster response times (in the UI)
38
+ minimal = "minimal"
39
+ # internal - allowed only in follower mode, only for the leader for upgrade purposes
40
+ leader = "leader"
41
+
42
+
26
43
  class ProjectMetadata(pydantic.BaseModel):
27
44
  name: str
28
45
  created: typing.Optional[datetime.datetime] = None
@@ -15,9 +15,26 @@
15
15
  import typing
16
16
 
17
17
  import pydantic
18
+ from deprecated import deprecated
19
+
20
+ import mlrun.common.types
18
21
 
19
22
 
20
23
  class RunIdentifier(pydantic.BaseModel):
21
24
  kind: typing.Literal["run"] = "run"
22
25
  uid: typing.Optional[str]
23
26
  iter: typing.Optional[int]
27
+
28
+
29
+ @deprecated(
30
+ version="1.7.0",
31
+ reason="mlrun.common.schemas.RunsFormat is deprecated and will be removed in 1.9.0. "
32
+ "Use mlrun.common.formatters.RunFormat instead.",
33
+ category=FutureWarning,
34
+ )
35
+ class RunsFormat(mlrun.common.types.StrEnum):
36
+ # No enrichment, data is pulled as-is from the database.
37
+ standard = "standard"
38
+
39
+ # Performs run enrichment, including the run's artifacts. Only available for the `get` run API.
40
+ full = "full"
@@ -96,7 +96,7 @@ class ScheduleUpdate(BaseModel):
96
96
  scheduled_object: Optional[Any]
97
97
  cron_trigger: Optional[Union[str, ScheduleCronTrigger]]
98
98
  desired_state: Optional[str]
99
- labels: Optional[dict] = {}
99
+ labels: Optional[dict] = None
100
100
  concurrency_limit: Optional[int]
101
101
  credentials: Credentials = Credentials()
102
102
 
mlrun/common/types.py CHANGED
@@ -29,3 +29,9 @@ class StrEnum(str, enum.Enum):
29
29
  class HTTPMethod(StrEnum):
30
30
  GET = "GET"
31
31
  POST = "POST"
32
+ DELETE = "DELETE"
33
+
34
+
35
+ class Operation(StrEnum):
36
+ ADD = "add"
37
+ REMOVE = "remove"
mlrun/config.py CHANGED
@@ -229,6 +229,9 @@ default_config = {
229
229
  "executing": "24h",
230
230
  }
231
231
  },
232
+ # When the module is reloaded, the maximum depth recursion configuration for the recursive reload
233
+ # function is used to prevent infinite loop
234
+ "reload_max_recursion_depth": 100,
232
235
  },
233
236
  "databricks": {
234
237
  "artifact_directory_path": "/mlrun_databricks_runtime/artifacts_dictionaries"
@@ -501,13 +504,12 @@ default_config = {
501
504
  "model_endpoint_monitoring": {
502
505
  "serving_stream_args": {"shard_count": 1, "retention_period_hours": 24},
503
506
  "application_stream_args": {"shard_count": 1, "retention_period_hours": 24},
504
- "drift_thresholds": {"default": {"possible_drift": 0.5, "drift_detected": 0.7}},
505
507
  # Store prefixes are used to handle model monitoring storing policies based on project and kind, such as events,
506
508
  # stream, and endpoints.
507
509
  "store_prefixes": {
508
510
  "default": "v3io:///users/pipelines/{project}/model-endpoints/{kind}",
509
511
  "user_space": "v3io:///projects/{project}/model-endpoints/{kind}",
510
- "stream": "",
512
+ "stream": "", # TODO: Delete in 1.9.0
511
513
  "monitoring_application": "v3io:///users/pipelines/{project}/monitoring-apps/",
512
514
  },
513
515
  # Offline storage path can be either relative or a full path. This path is used for general offline data
@@ -520,11 +522,12 @@ default_config = {
520
522
  "parquet_batching_max_events": 10_000,
521
523
  "parquet_batching_timeout_secs": timedelta(minutes=1).total_seconds(),
522
524
  # See mlrun.model_monitoring.db.stores.ObjectStoreFactory for available options
523
- "store_type": "v3io-nosql",
525
+ "store_type": "v3io-nosql", # TODO: Delete in 1.9.0
524
526
  "endpoint_store_connection": "",
525
527
  # See mlrun.model_monitoring.db.tsdb.ObjectTSDBFactory for available options
526
- "tsdb_connector_type": "v3io-tsdb",
527
528
  "tsdb_connection": "",
529
+ # See mlrun.common.schemas.model_monitoring.constants.StreamKind for available options
530
+ "stream_connection": "",
528
531
  },
529
532
  "secret_stores": {
530
533
  # Use only in testing scenarios (such as integration tests) to avoid using k8s for secrets (will use in-memory
@@ -657,7 +660,9 @@ default_config = {
657
660
  "failed_runs_grace_period": 3600,
658
661
  "verbose": True,
659
662
  # the number of workers which will be used to trigger the start log collection
660
- "concurrent_start_logs_workers": 15,
663
+ "concurrent_start_logs_workers": 50,
664
+ # the number of runs for which to start logs on api startup
665
+ "start_logs_startup_run_limit": 150,
661
666
  # the time in hours in which to start log collection from.
662
667
  # after upgrade, we might have runs which completed in the mean time or still in non-terminal state and
663
668
  # we want to collect their logs in the new log collection method (sidecar)
@@ -701,7 +706,12 @@ default_config = {
701
706
  "grafana_url": "",
702
707
  "alerts": {
703
708
  # supported modes: "enabled", "disabled".
704
- "mode": "enabled"
709
+ "mode": "enabled",
710
+ # maximum number of alerts we allow to be configured.
711
+ # user will get an error when exceeding this
712
+ "max_allowed": 10000,
713
+ # maximum allowed value for count in criteria field inside AlertConfig
714
+ "max_criteria_count": 100,
705
715
  },
706
716
  "auth_with_client_id": {
707
717
  "enabled": False,
@@ -806,6 +816,7 @@ class Config:
806
816
  ):
807
817
  """
808
818
  decodes and loads the config attribute to expected type
819
+
809
820
  :param attribute_path: the path in the default_config e.g. preemptible_nodes.node_selector
810
821
  :param expected_type: the object type valid values are : `dict`, `list` etc...
811
822
  :return: the expected type instance
@@ -931,24 +942,6 @@ class Config:
931
942
  f"is not allowed for iguazio version: {igz_version} < 3.5.1"
932
943
  )
933
944
 
934
- def resolve_kfp_url(self, namespace=None):
935
- if config.kfp_url:
936
- return config.kfp_url
937
- igz_version = self.get_parsed_igz_version()
938
- # TODO: When Iguazio 3.4 will deprecate we can remove this line
939
- if igz_version and igz_version <= semver.VersionInfo.parse("3.6.0-b1"):
940
- if namespace is None:
941
- if not config.namespace:
942
- raise mlrun.errors.MLRunNotFoundError(
943
- "For KubeFlow Pipelines to function, a namespace must be configured"
944
- )
945
- namespace = config.namespace
946
- # When instead of host we provided namespace we tackled this issue
947
- # https://github.com/canonical/bundle-kubeflow/issues/412
948
- # TODO: When we'll move to kfp 1.4.0 (server side) it should be resolved
949
- return f"http://ml-pipeline.{namespace}.svc.cluster.local:8888"
950
- return None
951
-
952
945
  def resolve_chief_api_url(self) -> str:
953
946
  if self.httpdb.clusterization.chief.url:
954
947
  return self.httpdb.clusterization.chief.url
@@ -1129,7 +1122,6 @@ class Config:
1129
1122
  if store_prefix_dict.get(kind):
1130
1123
  # Target exist in store prefix and has a valid string value
1131
1124
  return store_prefix_dict[kind].format(project=project, **kwargs)
1132
-
1133
1125
  if (
1134
1126
  function_name
1135
1127
  and function_name
@@ -208,6 +208,7 @@ class AzureBlobStore(DataStore):
208
208
  for key in spark_options:
209
209
  if key.startswith(prefix):
210
210
  account_key = key[len(prefix) :]
211
- url += f"@{account_key}"
211
+ if not url.endswith(account_key):
212
+ url += f"@{account_key}"
212
213
  break
213
214
  return url
@@ -21,7 +21,7 @@ from mlrun.datastore.datastore_profile import datastore_profile_read
21
21
  from mlrun.errors import err_to_str
22
22
  from mlrun.utils.helpers import get_local_file_schema
23
23
 
24
- from ..utils import DB_SCHEMA, run_keys
24
+ from ..utils import DB_SCHEMA, RunKeys
25
25
  from .base import DataItem, DataStore, HttpStore
26
26
  from .filestore import FileStore
27
27
  from .inmem import InMemoryStore
@@ -133,7 +133,7 @@ class StoreManager:
133
133
  return self._db
134
134
 
135
135
  def from_dict(self, struct: dict):
136
- stor_list = struct.get(run_keys.data_stores)
136
+ stor_list = struct.get(RunKeys.data_stores)
137
137
  if stor_list and isinstance(stor_list, list):
138
138
  for stor in stor_list:
139
139
  schema, endpoint, parsed_url = parse_url(stor.get("url"))
@@ -145,7 +145,7 @@ class StoreManager:
145
145
  self._stores[stor["name"]] = new_stor
146
146
 
147
147
  def to_dict(self, struct):
148
- struct[run_keys.data_stores] = [
148
+ struct[RunKeys.data_stores] = [
149
149
  stor.to_dict() for stor in self._stores.values() if stor.from_spec
150
150
  ]
151
151
 
@@ -55,8 +55,12 @@ class GoogleCloudStorageStore(DataStore):
55
55
  ) or self._get_secret_or_env("GOOGLE_APPLICATION_CREDENTIALS")
56
56
  if credentials:
57
57
  try:
58
- # Try to handle credentials as a json connection string
59
- token = json.loads(credentials)
58
+ # Try to handle credentials as a json connection string or do nothing if already a dict
59
+ token = (
60
+ credentials
61
+ if isinstance(credentials, dict)
62
+ else json.loads(credentials)
63
+ )
60
64
  except json.JSONDecodeError:
61
65
  # If it's not json, handle it as a filename
62
66
  token = credentials
@@ -30,13 +30,15 @@ def get_snowflake_password():
30
30
 
31
31
 
32
32
  def get_snowflake_spark_options(attributes):
33
+ if not attributes:
34
+ return {}
33
35
  return {
34
36
  "format": "net.snowflake.spark.snowflake",
35
37
  "sfURL": attributes.get("url"),
36
38
  "sfUser": attributes.get("user"),
37
39
  "sfPassword": get_snowflake_password(),
38
40
  "sfDatabase": attributes.get("database"),
39
- "sfSchema": attributes.get("schema"),
41
+ "sfSchema": attributes.get("db_schema"),
40
42
  "sfWarehouse": attributes.get("warehouse"),
41
43
  "application": "iguazio_platform",
42
44
  "TIMESTAMP_TYPE_MAPPING": "TIMESTAMP_LTZ",
@@ -747,7 +747,7 @@ class SnowflakeSource(BaseSourceDriver):
747
747
  url="...",
748
748
  user="...",
749
749
  database="...",
750
- schema="...",
750
+ db_schema="...",
751
751
  warehouse="...",
752
752
  )
753
753
 
@@ -762,7 +762,8 @@ class SnowflakeSource(BaseSourceDriver):
762
762
  :parameter url: URL of the snowflake cluster
763
763
  :parameter user: snowflake user
764
764
  :parameter database: snowflake database
765
- :parameter schema: snowflake schema
765
+ :parameter schema: snowflake schema - deprecated, use db_schema
766
+ :parameter db_schema: snowflake schema
766
767
  :parameter warehouse: snowflake warehouse
767
768
  """
768
769
 
@@ -774,6 +775,7 @@ class SnowflakeSource(BaseSourceDriver):
774
775
  self,
775
776
  name: str = "",
776
777
  key_field: str = None,
778
+ attributes: dict[str, object] = None,
777
779
  time_field: str = None,
778
780
  schedule: str = None,
779
781
  start_time=None,
@@ -783,21 +785,34 @@ class SnowflakeSource(BaseSourceDriver):
783
785
  user: str = None,
784
786
  database: str = None,
785
787
  schema: str = None,
788
+ db_schema: str = None,
786
789
  warehouse: str = None,
787
790
  **kwargs,
788
791
  ):
789
- attrs = {
790
- "query": query,
791
- "url": url,
792
- "user": user,
793
- "database": database,
794
- "schema": schema,
795
- "warehouse": warehouse,
796
- }
792
+ # TODO: Remove in 1.9.0
793
+ if schema:
794
+ warnings.warn(
795
+ "schema is deprecated in 1.7.0, and will be removed in 1.9.0, please use db_schema"
796
+ )
797
+ db_schema = db_schema or schema # TODO: Remove in 1.9.0
798
+
799
+ attributes = attributes or {}
800
+ if url:
801
+ attributes["url"] = url
802
+ if user:
803
+ attributes["user"] = user
804
+ if database:
805
+ attributes["database"] = database
806
+ if db_schema:
807
+ attributes["db_schema"] = db_schema
808
+ if warehouse:
809
+ attributes["warehouse"] = warehouse
810
+ if query:
811
+ attributes["query"] = query
797
812
 
798
813
  super().__init__(
799
814
  name,
800
- attributes=attrs,
815
+ attributes=attributes,
801
816
  key_field=key_field,
802
817
  time_field=time_field,
803
818
  schedule=schedule,
@@ -27,6 +27,8 @@ from .targets import get_online_target
27
27
 
28
28
  def is_store_uri(url):
29
29
  """detect if the uri starts with the store schema prefix"""
30
+ if not url:
31
+ return False
30
32
  return url.startswith(DB_SCHEMA + "://")
31
33
 
32
34