validio-sdk 5.2.0__tar.gz → 5.3.1__tar.gz

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.
Files changed (58) hide show
  1. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/PKG-INFO +1 -1
  2. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/pyproject.toml +1 -1
  3. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/_api/api.py +55 -5
  4. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/code/_import.py +1 -1
  5. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/code/plan.py +1 -5
  6. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_diff.py +6 -151
  7. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_server_resources.py +66 -18
  8. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/channels.py +17 -94
  9. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/credentials.py +243 -2
  10. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/filters.py +37 -152
  11. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/sources.py +178 -6
  12. validio_sdk-5.3.1/validio_sdk/resource/tests/__init__.py +0 -0
  13. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tests/test__diff.py +3 -2
  14. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tests/test__plan.py +0 -54
  15. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tests/test__resource.py +7 -47
  16. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/validators.py +40 -255
  17. validio_sdk-5.2.0/validio_sdk/resource/__init__.py +0 -6
  18. validio_sdk-5.2.0/validio_sdk/resource/_field_selector.py +0 -145
  19. validio_sdk-5.2.0/validio_sdk/resource/tests/test__channel.py +0 -137
  20. validio_sdk-5.2.0/validio_sdk/resource/tests/test__field_selector.py +0 -71
  21. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/LICENSE +0 -0
  22. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/README_PUBLIC.md +0 -0
  23. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/__init__.py +0 -0
  24. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/_api/__init__.py +0 -0
  25. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/client/__init__.py +0 -0
  26. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/client/client.py +0 -0
  27. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/code/__init__.py +0 -0
  28. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/code/_progress.py +0 -0
  29. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/code/apply.py +0 -0
  30. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/code/scaffold.py +0 -0
  31. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/code/settings.py +0 -0
  32. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/config.py +0 -0
  33. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/dbt.py +0 -0
  34. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/exception.py +0 -0
  35. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/metadata.py +0 -0
  36. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/py.typed +0 -0
  37. {validio_sdk-5.2.0/validio_sdk/resource/tests → validio_sdk-5.3.1/validio_sdk/resource}/__init__.py +0 -0
  38. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_diff_util.py +0 -0
  39. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_diffable.py +0 -0
  40. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_errors.py +0 -0
  41. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_resource.py +0 -0
  42. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_resource_graph.py +0 -0
  43. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_serde.py +0 -0
  44. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_update_namespace.py +0 -0
  45. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/_util.py +0 -0
  46. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/notification_rules.py +0 -0
  47. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/replacement.py +0 -0
  48. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/segmentations.py +0 -0
  49. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tags.py +0 -0
  50. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tests/assets/example_manifest.json +0 -0
  51. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tests/assets/expected_trimmed_manifest.json +0 -0
  52. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tests/test__dbt.py +0 -0
  53. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tests/test__sql_validation.py +0 -0
  54. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/tests/test_import.py +0 -0
  55. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/thresholds.py +0 -0
  56. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/resource/windows.py +0 -0
  57. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/scalars.py +0 -0
  58. {validio_sdk-5.2.0 → validio_sdk-5.3.1}/validio_sdk/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: validio-sdk
3
- Version: 5.2.0
3
+ Version: 5.3.1
4
4
  Summary: SDK to interact with the Validio platform
5
5
  Home-page: https://validio.io/
6
6
  License: Apache-2.0
@@ -3,7 +3,7 @@ name = "validio-sdk"
3
3
  # This version does not represent the released version or any tag. For each
4
4
  # release we automatically bump this before building and publishing so this
5
5
  # should be kept at 0.0.1dev1
6
- version = "5.2.0"
6
+ version = "5.3.1"
7
7
  description = "SDK to interact with the Validio platform"
8
8
  authors = ["Validio <support@validio.io>"]
9
9
  license = "Apache-2.0"
@@ -453,6 +453,22 @@ async def get_sources(
453
453
  schedule
454
454
  }
455
455
  }
456
+ ... on MsSqlServerSource {
457
+ config {
458
+ database
459
+ schema
460
+ table
461
+ schedule
462
+ }
463
+ }
464
+ ... on OracleSource {
465
+ config {
466
+ database
467
+ schema
468
+ table
469
+ schedule
470
+ }
471
+ }
456
472
  ... on PostgreSqlSource {
457
473
  config {
458
474
  database
@@ -992,6 +1008,37 @@ async def get_credentials(
992
1008
  }
993
1009
  enableCatalog
994
1010
  }
1011
+ ... on MsSqlServerCredential {
1012
+ config {
1013
+ host
1014
+ port
1015
+ database
1016
+ auth {
1017
+ __typename
1018
+ ... on MsSqlServerCredentialEntraId {
1019
+ clientId
1020
+ }
1021
+ ... on MsSqlServerCredentialUserPassword {
1022
+ user
1023
+ }
1024
+ }
1025
+ }
1026
+ enableCatalog
1027
+ }
1028
+ ... on OracleCredential {
1029
+ config {
1030
+ host
1031
+ port
1032
+ databaseRequired: database
1033
+ auth {
1034
+ __typename
1035
+ ... on OracleCredentialUserPassword {
1036
+ user
1037
+ }
1038
+ }
1039
+ }
1040
+ enableCatalog
1041
+ }
995
1042
  ... on PostgreSqlCredential {
996
1043
  config {
997
1044
  host
@@ -1117,7 +1164,13 @@ async def get_credentials(
1117
1164
  result = [result]
1118
1165
 
1119
1166
  for i, credential in enumerate(result):
1120
- _replace_aliases(credential.get("config", {}), [("powerBiAuth", "auth")])
1167
+ _replace_aliases(
1168
+ credential.get("config", {}),
1169
+ [
1170
+ ("powerBiAuth", "auth"),
1171
+ ("databaseRequired", "database"),
1172
+ ],
1173
+ )
1121
1174
  result[i] = credential
1122
1175
 
1123
1176
  return result[0] if return_first else result
@@ -1141,7 +1194,6 @@ async def get_channels(
1141
1194
  }
1142
1195
  ... on SlackChannel {
1143
1196
  config {
1144
- slackWebhookUrl: webhookUrl
1145
1197
  applicationLinkUrl
1146
1198
  slackChannelId
1147
1199
  interactiveMessageEnabled
@@ -1154,7 +1206,6 @@ async def get_channels(
1154
1206
  }
1155
1207
  ... on MsTeamsChannel {
1156
1208
  config {
1157
- msTeamsWebhookUrl: webhookUrl
1158
1209
  applicationLinkUrl
1159
1210
  msTeamsChannelId
1160
1211
  msTeamsInteractiveMessageEnabled: interactiveMessageEnabled
@@ -1223,8 +1274,6 @@ async def get_channels(
1223
1274
  _replace_aliases(
1224
1275
  ftr["config"],
1225
1276
  [
1226
- ("slackWebhookUrl", "webhookUrl"),
1227
- ("msTeamsWebhookUrl", "webhookUrl"),
1228
1277
  ("msTeamsInteractiveMessageEnabled", "interactiveMessageEnabled"),
1229
1278
  ("emailInteractiveMessageEnabled", "interactiveMessageEnabled"),
1230
1279
  ],
@@ -2523,6 +2572,7 @@ async def apply_source_action(
2523
2572
  result = {f"source{action.value}": {"errors": e.errors}}
2524
2573
  else:
2525
2574
  result = {f"source{action.value}": {"errors": [{"message": str(e)}]}}
2575
+
2526
2576
  return result[f"source{action.value}"]
2527
2577
 
2528
2578
 
@@ -277,7 +277,7 @@ async def _import(
277
277
  ("tags", resource_tags(r), None),
278
278
  ]
279
279
 
280
- if v._filter_resource_mode() and v.filter_name:
280
+ if v.filter_name:
281
281
  filter_ = import_ctx.get_variable(Filter, v.filter_name)
282
282
  inits.append(("filter", filter_, None))
283
283
 
@@ -24,7 +24,7 @@ from validio_sdk.resource._resource import (
24
24
  )
25
25
  from validio_sdk.resource._server_resources import load_resources
26
26
  from validio_sdk.resource._util import SourceSchemaReinference
27
- from validio_sdk.resource.channels import Channel, WebhookChannel
27
+ from validio_sdk.resource.channels import WebhookChannel
28
28
  from validio_sdk.resource.tags import Tag
29
29
 
30
30
 
@@ -286,10 +286,6 @@ def _create_resource_diff_object(
286
286
  if not show_secrets and hasattr(r, "_secret_fields"):
287
287
  secret_fields = r._secret_fields()
288
288
 
289
- # Workaround for Channel having a special secret field
290
- if isinstance(r, Channel):
291
- secret_fields.update(r._deprecated_secret_fields())
292
-
293
289
  if secret_fields:
294
290
  for field in secret_fields:
295
291
  # We want to avoid overriding webhook_url if it is None already
@@ -1,7 +1,5 @@
1
1
  import asyncio
2
- import copy
3
2
  import dataclasses
4
- import re
5
3
  import typing
6
4
  from dataclasses import dataclass
7
5
  from typing import (
@@ -9,7 +7,6 @@ from typing import (
9
7
  Any,
10
8
  Optional,
11
9
  TypeVar,
12
- cast,
13
10
  )
14
11
 
15
12
  from camel_converter import to_snake
@@ -18,7 +15,6 @@ from gql.transport.exceptions import TransportQueryError
18
15
  from validio_sdk._api.api import secrets_changed_by_field, split_to_n_chunks
19
16
  from validio_sdk.client import Session
20
17
  from validio_sdk.exception import ValidioBugError, ValidioError
21
- from validio_sdk.resource._diff_util import must_find_source
22
18
  from validio_sdk.resource._diffable import (
23
19
  ApiSecretChangeNestedResource,
24
20
  Diffable,
@@ -28,10 +24,8 @@ from validio_sdk.resource._errors import (
28
24
  max_resource_depth_exceeded,
29
25
  updated_resource_type_mismatch_exception,
30
26
  )
31
- from validio_sdk.resource._field_selector import SelectorWithFieldName
32
27
  from validio_sdk.resource._resource import CREATE_ONLY_RESOURCES, DiffContext, Resource
33
28
  from validio_sdk.resource._util import SourceSchemaReinference, _sanitize_error
34
- from validio_sdk.resource.channels import Channel
35
29
  from validio_sdk.resource.replacement import (
36
30
  CascadeReplacementReason,
37
31
  ImmutableFieldReplacementReason,
@@ -41,7 +35,6 @@ from validio_sdk.resource.replacement import (
41
35
  from validio_sdk.resource.segmentations import Segmentation
42
36
  from validio_sdk.resource.sources import Source
43
37
  from validio_sdk.resource.tags import Tag
44
- from validio_sdk.resource.validators import Reference, Validator
45
38
  from validio_sdk.resource.windows import TumblingWindow
46
39
 
47
40
  if TYPE_CHECKING:
@@ -179,51 +172,29 @@ async def diff_resource_graph(
179
172
  server_ctx: DiffContext,
180
173
  import_mode: bool = False,
181
174
  ) -> GraphDiff:
182
- partial_diff = _diff_resource_graph(
175
+ graph_diff = _diff_resource_graph(
183
176
  namespace=namespace,
184
177
  manifest_ctx=manifest_ctx,
185
178
  server_ctx=server_ctx,
186
- for_validators=False,
187
179
  import_mode=import_mode,
188
180
  )
189
181
 
190
- # Enrich resource_graph. We do this before expanding field selectors
191
- # because the latter depends on the schema for all sources being present.
192
182
  await enrich_resource_graph(
193
183
  manifest_ctx=manifest_ctx,
194
184
  server_ctx=server_ctx,
195
- graph=partial_diff,
185
+ graph=graph_diff,
196
186
  session=session,
197
187
  schema_reinference=schema_reinference,
198
188
  show_secrets=show_secrets,
199
189
  )
200
190
 
201
- # Expand field selector for validators.
202
- expand_validator_field_selectors(manifest_ctx)
203
-
204
- # Now after expanding field selectors, we can diff validators.
205
- validators_diff = _diff_resource_graph(
206
- namespace=namespace,
207
- manifest_ctx=manifest_ctx,
208
- server_ctx=server_ctx,
209
- for_validators=True,
210
- import_mode=import_mode,
211
- )
212
-
213
- final_diff = partial_diff
214
- final_diff.to_create.validators = validators_diff.to_create.validators
215
- final_diff.to_update.validators = validators_diff.to_update.validators
216
- final_diff.to_delete.validators = validators_diff.to_delete.validators
217
- for k, v in validators_diff.replacement_ctx.validators.items():
218
- final_diff.replacement_ctx.validators[k] = v
219
-
220
191
  _compute_replacements(
221
192
  manifest_ctx=manifest_ctx,
222
193
  server_ctx=server_ctx,
223
- graph_diff=final_diff,
194
+ graph_diff=graph_diff,
224
195
  )
225
196
 
226
- return final_diff
197
+ return graph_diff
227
198
 
228
199
 
229
200
  def _compute_replacements(
@@ -281,8 +252,7 @@ def _visit_resource_to_replace(
281
252
  to_delete: dict[str, Resource] = getattr(graph_diff.to_delete, resource_type)
282
253
 
283
254
  # Remove the resource from the update list.
284
- if resource_name in to_update:
285
- del to_update[resource_name]
255
+ to_update.pop(resource_name, None)
286
256
 
287
257
  # Flag the resource to be created.
288
258
  manifest_resources: dict[str, Resource] = getattr(manifest_ctx, resource_type)
@@ -406,85 +376,10 @@ def _visit_resource_to_cascade_update(
406
376
  )
407
377
 
408
378
 
409
- def expand_validator_field_selectors(manifest_ctx: DiffContext) -> None:
410
- for name in list(manifest_ctx.validators.keys()):
411
- template = manifest_ctx.validators[name]
412
-
413
- source_field_selector: SelectorWithFieldName | None = getattr(
414
- template, "_field_selector", None
415
- )
416
- reference_field_selector: dict[str, str] | None = getattr(
417
- template, "_reference_field_selector", None
418
- )
419
- filter_field_selector: SelectorWithFieldName | None = (
420
- getattr(template.filter, "_field_selector", None)
421
- if template.filter
422
- else None
423
- )
424
-
425
- if source_field_selector:
426
- field_selector = source_field_selector
427
- elif filter_field_selector:
428
- field_selector = filter_field_selector
429
- else:
430
- continue
431
-
432
- source = must_find_source(manifest_ctx, template.source_name)
433
- if source.jtd_schema is None:
434
- # If we have no schema then it means we're doing a diff where the
435
- # source's credential has not yet been created - which means we can't
436
- # do schema inference. As a result, we can't yet expand the selector.
437
- continue
438
-
439
- if source_field_selector:
440
- delattr(template, "_field_selector")
441
- if reference_field_selector:
442
- delattr(template, "_reference_field_selector")
443
- if filter_field_selector:
444
- delattr(template.filter, "_field_selector")
445
-
446
- # Remove the placeholder validator.
447
- del manifest_ctx.validators[name]
448
-
449
- fields = field_selector.field_selector._get_matching_fields(
450
- cast(Any, source.jtd_schema)
451
- )
452
-
453
- # We don't want to deep copy the entire resource graph
454
- resource_graph = template._resource_graph
455
- template._resource_graph = None # type: ignore
456
- for field in fields:
457
- validator = copy.deepcopy(template)
458
- validator._resource_graph = resource_graph
459
-
460
- # We must obey to our own naming convention so we drop everything
461
- # that's not valid.
462
- resource_name = validator.name % {"field": field}
463
- resource_name = resource_name.replace(" ", "_").lower()
464
- resource_name = re.sub(r"[^a-z0-9_.-]", "_", resource_name)
465
- validator.name = resource_name
466
-
467
- if source_field_selector:
468
- setattr(validator, field_selector.field_name, field)
469
-
470
- if reference_field_selector:
471
- setattr(validator, reference_field_selector["field_name"], field)
472
-
473
- if filter_field_selector:
474
- setattr(
475
- validator.filter,
476
- field_selector.field_name,
477
- field,
478
- )
479
-
480
- manifest_ctx.validators[resource_name] = validator
481
-
482
-
483
379
  def _diff_resource_graph(
484
380
  namespace: str,
485
381
  manifest_ctx: DiffContext,
486
382
  server_ctx: DiffContext,
487
- for_validators: bool | None = None,
488
383
  import_mode: bool = False,
489
384
  ) -> GraphDiff:
490
385
  # Backwards compatibility: Here we note the filters that
@@ -506,14 +401,6 @@ def _diff_resource_graph(
506
401
  for field in fields:
507
402
  if field in CREATE_ONLY_RESOURCES:
508
403
  continue
509
-
510
- include_diff = (
511
- True
512
- if for_validators is None
513
- else (field == "validators") == for_validators
514
- )
515
- if not include_diff:
516
- continue
517
404
  diff_by_resource[field] = diff_fn(
518
405
  namespace, getattr(manifest_ctx, field), getattr(server_ctx, field)
519
406
  )
@@ -676,23 +563,6 @@ def diff(
676
563
  if isinstance(manifest_object, Resource) and manifest_object.ignore_changes:
677
564
  return None
678
565
 
679
- # NOTE: Backwards compatibility while we transition to Filter resources.
680
- # If we're about to diff a validator where the manifest validator still uses
681
- # the JSONFilterExpression mode, then force the server object to work
682
- # in the JSONFilterExpression mode so that we can compare the same fields.
683
- # Same for validator reference.
684
- if (
685
- isinstance(manifest_object, (Reference, Validator))
686
- and
687
- # NOTE: the server resource is always the Validator. Even if
688
- # the server object is potentially the nested 'Reference'.
689
- # This is mostly for type-checking.
690
- isinstance(server_resource, Validator)
691
- and isinstance(manifest_resource, Validator)
692
- ) and not manifest_object._filter_resource_mode():
693
- manifest_resource._force_filter_expression_mode()
694
- server_resource._force_filter_expression_mode()
695
-
696
566
  if isinstance(server_resource, Segmentation) and isinstance(
697
567
  manifest_resource, Segmentation
698
568
  ):
@@ -752,20 +622,6 @@ def diff(
752
622
  server = getattr(server_object, field)
753
623
 
754
624
  if manifest != server:
755
- # This is a temporary fix to support marking deprecated secret fields as
756
- # changed on a `Channel`. If the field is both in `_mutable_fields`
757
- # and also in `_deprecated_secret_fields` we will flag the field in
758
- # `secret_fields_changed` if there has been an update. This ensures
759
- # that the value is redacted by default when displaying the config.
760
- secret_fields_changed = None
761
- if (
762
- isinstance(manifest_object, Channel)
763
- and field in manifest_object._deprecated_secret_fields()
764
- ):
765
- secret_fields_changed = {
766
- field: True,
767
- }
768
-
769
625
  # Whenever we find there's a change to make, grab all fields on both
770
626
  # resource versions so that we can present them as a diff.
771
627
  # Regardless of at what depth we find a change, the diff we present
@@ -774,7 +630,6 @@ def diff(
774
630
  return ResourceUpdate(
775
631
  manifest_resource,
776
632
  server_resource,
777
- secret_fields_changed=secret_fields_changed,
778
633
  )
779
634
 
780
635
  # Some fields require the resource to be re-created if the type changes
@@ -974,7 +829,7 @@ async def check_for_source_schema_changes(
974
829
  manifest_source, server_source
975
830
  )
976
831
 
977
- # Ensure the source has a schema in case we need it in a field selector.
832
+ # Ensure the source has a schema in case we need it later on.
978
833
  if manifest_source.jtd_schema is None:
979
834
  manifest_source.jtd_schema = server_source.jtd_schema
980
835
 
@@ -10,16 +10,13 @@ from gql.transport.exceptions import TransportQueryError
10
10
  import validio_sdk
11
11
  from validio_sdk._api import api
12
12
  from validio_sdk.client import Session
13
- from validio_sdk.client.client import Client
14
13
  from validio_sdk.code._progress import ProgressBar
15
- from validio_sdk.config import Config, ValidioConfig
16
14
  from validio_sdk.exception import ValidioBugError, ValidioError
17
15
  from validio_sdk.resource._diff import (
18
16
  DiffContext,
19
17
  GraphDiff,
20
18
  ResourceUpdate,
21
19
  ResourceUpdates,
22
- expand_validator_field_selectors,
23
20
  infer_schemas,
24
21
  )
25
22
  from validio_sdk.resource._diff_util import (
@@ -59,6 +56,13 @@ from validio_sdk.resource.credentials import (
59
56
  LookerCredential,
60
57
  MsPowerBiCredential,
61
58
  MsPowerBiCredentialAuthEntraId,
59
+ MsSqlServerCredential,
60
+ MsSqlServerCredentialAuth,
61
+ MsSqlServerCredentialEntraId,
62
+ MsSqlServerCredentialUserPassword,
63
+ OracleCredential,
64
+ OracleCredentialAuth,
65
+ OracleCredentialUserPassword,
62
66
  PostgreSqlCredential,
63
67
  SigmaCredential,
64
68
  SnowflakeCredential,
@@ -314,12 +318,12 @@ async def load_credentials(
314
318
  auth_type = c["config"]["auth"]["__typename"]
315
319
 
316
320
  if auth_type == "SnowflakeCredentialUserPassword":
317
- auth: SnowflakeCredentialAuth = SnowflakeCredentialUserPassword(
321
+ sf_auth: SnowflakeCredentialAuth = SnowflakeCredentialUserPassword(
318
322
  user=c["config"]["auth"]["user"],
319
323
  password="UNSET",
320
324
  )
321
325
  elif auth_type == "SnowflakeCredentialKeyPair":
322
- auth = SnowflakeCredentialKeyPair(
326
+ sf_auth = SnowflakeCredentialKeyPair(
323
327
  user=c["config"]["auth"]["user"],
324
328
  private_key="UNSET",
325
329
  private_key_passphrase="UNSET",
@@ -330,13 +334,64 @@ async def load_credentials(
330
334
  credential = SnowflakeCredential(
331
335
  name=name,
332
336
  account=c["config"]["account"],
333
- auth=auth,
337
+ auth=sf_auth,
334
338
  warehouse=c["config"]["warehouse"],
335
339
  role=c["config"]["role"],
336
340
  display_name=display_name,
337
341
  enable_catalog=c["enableCatalog"],
338
342
  __internal__=g,
339
343
  )
344
+ case "MsSqlServerCredential":
345
+ auth_type = c["config"]["auth"]["__typename"]
346
+
347
+ if auth_type == "MsSqlServerCredentialUserPassword":
348
+ ms_auth: MsSqlServerCredentialAuth = (
349
+ MsSqlServerCredentialUserPassword(
350
+ user=c["config"]["auth"]["user"],
351
+ password="UNSET",
352
+ )
353
+ )
354
+ elif auth_type == "MsSqlServerCredentialEntraId":
355
+ ms_auth = MsSqlServerCredentialEntraId(
356
+ client_id=c["config"]["auth"]["clientId"],
357
+ client_secret="UNSET",
358
+ )
359
+ else:
360
+ raise ValidioBugError(
361
+ f"Unknown MsSqlServer auth type: '{auth_type}'"
362
+ )
363
+
364
+ credential = MsSqlServerCredential(
365
+ name=name,
366
+ host=c["config"]["host"],
367
+ port=c["config"]["port"],
368
+ database=c["config"]["database"],
369
+ auth=ms_auth,
370
+ display_name=display_name,
371
+ enable_catalog=c["enableCatalog"],
372
+ __internal__=g,
373
+ )
374
+ case "OracleCredential":
375
+ auth_type = c["config"]["auth"]["__typename"]
376
+
377
+ if auth_type == "OracleCredentialUserPassword":
378
+ oracle_auth: OracleCredentialAuth = OracleCredentialUserPassword(
379
+ user=c["config"]["auth"]["user"],
380
+ password="UNSET",
381
+ )
382
+ else:
383
+ raise ValidioBugError(f"Unknown Oracle auth type: '{auth_type}'")
384
+
385
+ credential = OracleCredential(
386
+ name=name,
387
+ host=c["config"]["host"],
388
+ port=c["config"]["port"],
389
+ database=c["config"]["database"],
390
+ auth=oracle_auth,
391
+ display_name=display_name,
392
+ enable_catalog=c["enableCatalog"],
393
+ __internal__=g,
394
+ )
340
395
  case "KafkaSslCredential":
341
396
  credential = KafkaSslCredential(
342
397
  name=name,
@@ -443,7 +498,6 @@ async def load_channels(
443
498
 
444
499
  cfg = ch["config"]
445
500
  application_link_url = cfg["applicationLinkUrl"]
446
- unset_or_none = None if cfg.get("webhookUrl") else "UNSET"
447
501
  interactive_message_enabled = cfg.get("interactiveMessageEnabled", None)
448
502
  display_name = ch["name"]
449
503
  # The 'secret' parts of a channel are left unset since they are not
@@ -454,10 +508,9 @@ async def load_channels(
454
508
  name=name,
455
509
  application_link_url=application_link_url,
456
510
  ms_teams_channel_id=cfg["msTeamsChannelId"],
457
- client_id=unset_or_none,
458
- client_secret=unset_or_none,
511
+ client_id="UNSET",
512
+ client_secret="UNSET",
459
513
  interactive_message_enabled=interactive_message_enabled,
460
- webhook_url=cfg["webhookUrl"],
461
514
  display_name=display_name,
462
515
  __internal__=g,
463
516
  )
@@ -466,11 +519,10 @@ async def load_channels(
466
519
  name=name,
467
520
  application_link_url=application_link_url,
468
521
  slack_channel_id=cfg["slackChannelId"],
469
- token=unset_or_none,
470
- signing_secret=unset_or_none,
471
- app_token=unset_or_none,
522
+ token="UNSET",
523
+ signing_secret="UNSET",
524
+ app_token="UNSET",
472
525
  interactive_message_enabled=interactive_message_enabled,
473
- webhook_url=cfg["webhookUrl"],
474
526
  display_name=display_name,
475
527
  __internal__=g,
476
528
  )
@@ -839,10 +891,6 @@ async def apply_updates_on_server(
839
891
  dry_run_sql=dry_run_sql,
840
892
  )
841
893
 
842
- # Now we should have all source schemas available. We can expand
843
- # field selectors.
844
- expand_validator_field_selectors(ctx)
845
-
846
894
  # Then apply updates.
847
895
  await apply_updates(
848
896
  namespace=namespace,