validio-sdk 5.2.0__tar.gz → 5.3.0__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.
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/PKG-INFO +1 -1
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/pyproject.toml +1 -1
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/_api/api.py +55 -1
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_diff.py +5 -115
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_server_resources.py +61 -10
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/credentials.py +243 -2
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/filters.py +11 -49
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/sources.py +178 -6
- validio_sdk-5.3.0/validio_sdk/resource/tests/__init__.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/test__resource.py +7 -45
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/validators.py +12 -141
- validio_sdk-5.2.0/validio_sdk/resource/__init__.py +0 -6
- validio_sdk-5.2.0/validio_sdk/resource/_field_selector.py +0 -145
- validio_sdk-5.2.0/validio_sdk/resource/tests/test__field_selector.py +0 -71
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/LICENSE +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/README_PUBLIC.md +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/__init__.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/_api/__init__.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/client/__init__.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/client/client.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/code/__init__.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/code/_import.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/code/_progress.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/code/apply.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/code/plan.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/code/scaffold.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/code/settings.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/config.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/dbt.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/exception.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/metadata.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/py.typed +0 -0
- {validio_sdk-5.2.0/validio_sdk/resource/tests → validio_sdk-5.3.0/validio_sdk/resource}/__init__.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_diff_util.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_diffable.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_errors.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_resource.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_resource_graph.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_serde.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_update_namespace.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/_util.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/channels.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/notification_rules.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/replacement.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/segmentations.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tags.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/assets/example_manifest.json +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/assets/expected_trimmed_manifest.json +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/test__channel.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/test__dbt.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/test__diff.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/test__plan.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/test__sql_validation.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/tests/test_import.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/thresholds.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/resource/windows.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/scalars.py +0 -0
- {validio_sdk-5.2.0 → validio_sdk-5.3.0}/validio_sdk/util.py +0 -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.
|
|
6
|
+
version = "5.3.0"
|
|
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(
|
|
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
|
|
@@ -2523,6 +2576,7 @@ async def apply_source_action(
|
|
|
2523
2576
|
result = {f"source{action.value}": {"errors": e.errors}}
|
|
2524
2577
|
else:
|
|
2525
2578
|
result = {f"source{action.value}": {"errors": [{"message": str(e)}]}}
|
|
2579
|
+
|
|
2526
2580
|
return result[f"source{action.value}"]
|
|
2527
2581
|
|
|
2528
2582
|
|
|
@@ -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,7 +24,6 @@ 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
29
|
from validio_sdk.resource.channels import Channel
|
|
@@ -179,51 +174,29 @@ async def diff_resource_graph(
|
|
|
179
174
|
server_ctx: DiffContext,
|
|
180
175
|
import_mode: bool = False,
|
|
181
176
|
) -> GraphDiff:
|
|
182
|
-
|
|
177
|
+
graph_diff = _diff_resource_graph(
|
|
183
178
|
namespace=namespace,
|
|
184
179
|
manifest_ctx=manifest_ctx,
|
|
185
180
|
server_ctx=server_ctx,
|
|
186
|
-
for_validators=False,
|
|
187
181
|
import_mode=import_mode,
|
|
188
182
|
)
|
|
189
183
|
|
|
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
184
|
await enrich_resource_graph(
|
|
193
185
|
manifest_ctx=manifest_ctx,
|
|
194
186
|
server_ctx=server_ctx,
|
|
195
|
-
graph=
|
|
187
|
+
graph=graph_diff,
|
|
196
188
|
session=session,
|
|
197
189
|
schema_reinference=schema_reinference,
|
|
198
190
|
show_secrets=show_secrets,
|
|
199
191
|
)
|
|
200
192
|
|
|
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
193
|
_compute_replacements(
|
|
221
194
|
manifest_ctx=manifest_ctx,
|
|
222
195
|
server_ctx=server_ctx,
|
|
223
|
-
graph_diff=
|
|
196
|
+
graph_diff=graph_diff,
|
|
224
197
|
)
|
|
225
198
|
|
|
226
|
-
return
|
|
199
|
+
return graph_diff
|
|
227
200
|
|
|
228
201
|
|
|
229
202
|
def _compute_replacements(
|
|
@@ -406,85 +379,10 @@ def _visit_resource_to_cascade_update(
|
|
|
406
379
|
)
|
|
407
380
|
|
|
408
381
|
|
|
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
382
|
def _diff_resource_graph(
|
|
484
383
|
namespace: str,
|
|
485
384
|
manifest_ctx: DiffContext,
|
|
486
385
|
server_ctx: DiffContext,
|
|
487
|
-
for_validators: bool | None = None,
|
|
488
386
|
import_mode: bool = False,
|
|
489
387
|
) -> GraphDiff:
|
|
490
388
|
# Backwards compatibility: Here we note the filters that
|
|
@@ -506,14 +404,6 @@ def _diff_resource_graph(
|
|
|
506
404
|
for field in fields:
|
|
507
405
|
if field in CREATE_ONLY_RESOURCES:
|
|
508
406
|
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
407
|
diff_by_resource[field] = diff_fn(
|
|
518
408
|
namespace, getattr(manifest_ctx, field), getattr(server_ctx, field)
|
|
519
409
|
)
|
|
@@ -974,7 +864,7 @@ async def check_for_source_schema_changes(
|
|
|
974
864
|
manifest_source, server_source
|
|
975
865
|
)
|
|
976
866
|
|
|
977
|
-
# Ensure the source has a schema in case we need it
|
|
867
|
+
# Ensure the source has a schema in case we need it later on.
|
|
978
868
|
if manifest_source.jtd_schema is None:
|
|
979
869
|
manifest_source.jtd_schema = server_source.jtd_schema
|
|
980
870
|
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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=
|
|
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,
|
|
@@ -839,10 +894,6 @@ async def apply_updates_on_server(
|
|
|
839
894
|
dry_run_sql=dry_run_sql,
|
|
840
895
|
)
|
|
841
896
|
|
|
842
|
-
# Now we should have all source schemas available. We can expand
|
|
843
|
-
# field selectors.
|
|
844
|
-
expand_validator_field_selectors(ctx)
|
|
845
|
-
|
|
846
897
|
# Then apply updates.
|
|
847
898
|
await apply_updates(
|
|
848
899
|
namespace=namespace,
|
|
@@ -713,8 +713,6 @@ class SnowflakeCredential(Credential):
|
|
|
713
713
|
|
|
714
714
|
:param name: Unique resource name assigned to the credential
|
|
715
715
|
:param account: Snowflake account identifier.
|
|
716
|
-
:param user: Deprecated, use auth instead.
|
|
717
|
-
:param password: Deprecated, use auth instead.
|
|
718
716
|
:param auth: Credentials to use for authentication.
|
|
719
717
|
:param warehouse: Snowflake virtual warehouse to use to run queries.
|
|
720
718
|
:param role: Snowflake role to assume when running queries.
|
|
@@ -1308,6 +1306,249 @@ class AzureSynapseSqlCredential(AzureSynapseCredential):
|
|
|
1308
1306
|
return {"password"}
|
|
1309
1307
|
|
|
1310
1308
|
|
|
1309
|
+
class MsSqlServerCredentialUserPassword(ApiSecretChangeNestedResource):
|
|
1310
|
+
"""MsSql-compatible credential via user-password auth."""
|
|
1311
|
+
|
|
1312
|
+
def __init__(
|
|
1313
|
+
self,
|
|
1314
|
+
user: str,
|
|
1315
|
+
password: str,
|
|
1316
|
+
):
|
|
1317
|
+
"""
|
|
1318
|
+
Constructor.
|
|
1319
|
+
|
|
1320
|
+
:param user: User name.
|
|
1321
|
+
:param password: Password.
|
|
1322
|
+
"""
|
|
1323
|
+
self.user = user
|
|
1324
|
+
self.password = password
|
|
1325
|
+
|
|
1326
|
+
def _api_variant_name(self) -> str:
|
|
1327
|
+
return "userPassword"
|
|
1328
|
+
|
|
1329
|
+
def _immutable_fields(self) -> set[str]:
|
|
1330
|
+
return set({})
|
|
1331
|
+
|
|
1332
|
+
def _mutable_fields(self) -> set[str]:
|
|
1333
|
+
return {"user"}
|
|
1334
|
+
|
|
1335
|
+
def _secret_fields(self) -> set[str]:
|
|
1336
|
+
return {"password"}
|
|
1337
|
+
|
|
1338
|
+
def _nested_objects(
|
|
1339
|
+
self,
|
|
1340
|
+
) -> dict[str, Optional["Diffable | list[Diffable]"] | None]:
|
|
1341
|
+
return {}
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
class MsSqlServerCredentialEntraId(ApiSecretChangeNestedResource):
|
|
1345
|
+
"""MsSql-compatible credential via entra-id auth."""
|
|
1346
|
+
|
|
1347
|
+
def __init__(
|
|
1348
|
+
self,
|
|
1349
|
+
client_id: str,
|
|
1350
|
+
client_secret: str,
|
|
1351
|
+
):
|
|
1352
|
+
"""
|
|
1353
|
+
Constructor.
|
|
1354
|
+
|
|
1355
|
+
:param client_id: The client ID of your Azure registered application.
|
|
1356
|
+
:param client_secret: The client secret of your Azure registered application.
|
|
1357
|
+
"""
|
|
1358
|
+
self.client_id = client_id
|
|
1359
|
+
self.client_secret = client_secret
|
|
1360
|
+
|
|
1361
|
+
def _api_variant_name(self) -> str:
|
|
1362
|
+
return "entraId"
|
|
1363
|
+
|
|
1364
|
+
def _immutable_fields(self) -> set[str]:
|
|
1365
|
+
return set({})
|
|
1366
|
+
|
|
1367
|
+
def _mutable_fields(self) -> set[str]:
|
|
1368
|
+
return {"client_id"}
|
|
1369
|
+
|
|
1370
|
+
def _secret_fields(self) -> set[str]:
|
|
1371
|
+
return {"client_secret"}
|
|
1372
|
+
|
|
1373
|
+
def _nested_objects(
|
|
1374
|
+
self,
|
|
1375
|
+
) -> dict[str, Optional["Diffable | list[Diffable]"] | None]:
|
|
1376
|
+
return {}
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
MsSqlServerCredentialAuth = Union[
|
|
1380
|
+
MsSqlServerCredentialUserPassword, MsSqlServerCredentialEntraId
|
|
1381
|
+
]
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
class MsSqlServerCredential(Credential):
|
|
1385
|
+
"""Credential to connect to a Microsoft Sql Server warehouse."""
|
|
1386
|
+
|
|
1387
|
+
def __init__(
|
|
1388
|
+
self,
|
|
1389
|
+
name: str,
|
|
1390
|
+
host: str,
|
|
1391
|
+
port: int,
|
|
1392
|
+
auth: MsSqlServerCredentialAuth,
|
|
1393
|
+
database: str | None = None,
|
|
1394
|
+
enable_catalog: bool = False,
|
|
1395
|
+
display_name: str | None = None,
|
|
1396
|
+
ignore_changes: bool = False,
|
|
1397
|
+
__internal__: ResourceGraph | None = None,
|
|
1398
|
+
):
|
|
1399
|
+
"""
|
|
1400
|
+
Constructor.
|
|
1401
|
+
|
|
1402
|
+
:param name: Unique resource name assigned to the credential
|
|
1403
|
+
:param host: Host address of the server.
|
|
1404
|
+
:param port: Port number of the server.
|
|
1405
|
+
:param auth: Credentials to use for authentication.
|
|
1406
|
+
:param database: Name of the database to connect to
|
|
1407
|
+
:param enable_catalog: If set to true, this credential will
|
|
1408
|
+
be used to fetch catalog information.
|
|
1409
|
+
:param display_name: Human-readable name for the credential. This name is
|
|
1410
|
+
visible in the UI and does not need to be unique.
|
|
1411
|
+
:param ignore_changes: If set to true, changes to the resource will be ignored.
|
|
1412
|
+
"""
|
|
1413
|
+
super().__init__(
|
|
1414
|
+
name=name,
|
|
1415
|
+
display_name=display_name,
|
|
1416
|
+
ignore_changes=ignore_changes,
|
|
1417
|
+
__internal__=__internal__,
|
|
1418
|
+
)
|
|
1419
|
+
|
|
1420
|
+
self.host = host
|
|
1421
|
+
self.port = port
|
|
1422
|
+
self.auth = auth
|
|
1423
|
+
self.database = database
|
|
1424
|
+
self.enable_catalog = enable_catalog
|
|
1425
|
+
|
|
1426
|
+
def _immutable_fields(self) -> set[str]:
|
|
1427
|
+
return set({})
|
|
1428
|
+
|
|
1429
|
+
def _mutable_fields(self) -> set[str]:
|
|
1430
|
+
return {
|
|
1431
|
+
*super()._mutable_fields(),
|
|
1432
|
+
*{
|
|
1433
|
+
"host",
|
|
1434
|
+
"port",
|
|
1435
|
+
"database",
|
|
1436
|
+
"enable_catalog",
|
|
1437
|
+
},
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
def _secret_fields(self) -> set[str]:
|
|
1441
|
+
return set()
|
|
1442
|
+
|
|
1443
|
+
def _nested_objects(
|
|
1444
|
+
self,
|
|
1445
|
+
) -> dict[str, Optional["Diffable | list[Diffable]"] | None]:
|
|
1446
|
+
return {"auth": self.auth}
|
|
1447
|
+
|
|
1448
|
+
|
|
1449
|
+
class OracleCredentialUserPassword(ApiSecretChangeNestedResource):
|
|
1450
|
+
"""Oracle credential via user-password auth."""
|
|
1451
|
+
|
|
1452
|
+
def __init__(
|
|
1453
|
+
self,
|
|
1454
|
+
user: str,
|
|
1455
|
+
password: str,
|
|
1456
|
+
):
|
|
1457
|
+
"""
|
|
1458
|
+
Constructor.
|
|
1459
|
+
|
|
1460
|
+
:param user: User name.
|
|
1461
|
+
:param password: Password.
|
|
1462
|
+
"""
|
|
1463
|
+
self.user = user
|
|
1464
|
+
self.password = password
|
|
1465
|
+
|
|
1466
|
+
def _api_variant_name(self) -> str:
|
|
1467
|
+
return "userPassword"
|
|
1468
|
+
|
|
1469
|
+
def _immutable_fields(self) -> set[str]:
|
|
1470
|
+
return set({})
|
|
1471
|
+
|
|
1472
|
+
def _mutable_fields(self) -> set[str]:
|
|
1473
|
+
return {"user"}
|
|
1474
|
+
|
|
1475
|
+
def _secret_fields(self) -> set[str]:
|
|
1476
|
+
return {"password"}
|
|
1477
|
+
|
|
1478
|
+
def _nested_objects(
|
|
1479
|
+
self,
|
|
1480
|
+
) -> dict[str, Optional["Diffable | list[Diffable]"] | None]:
|
|
1481
|
+
return {}
|
|
1482
|
+
|
|
1483
|
+
|
|
1484
|
+
OracleCredentialAuth = Union[OracleCredentialUserPassword]
|
|
1485
|
+
|
|
1486
|
+
|
|
1487
|
+
class OracleCredential(Credential):
|
|
1488
|
+
"""Credential to connect to an Oracle database."""
|
|
1489
|
+
|
|
1490
|
+
def __init__(
|
|
1491
|
+
self,
|
|
1492
|
+
name: str,
|
|
1493
|
+
host: str,
|
|
1494
|
+
port: int,
|
|
1495
|
+
database: str,
|
|
1496
|
+
auth: OracleCredentialAuth,
|
|
1497
|
+
enable_catalog: bool = False,
|
|
1498
|
+
display_name: str | None = None,
|
|
1499
|
+
ignore_changes: bool = False,
|
|
1500
|
+
__internal__: ResourceGraph | None = None,
|
|
1501
|
+
):
|
|
1502
|
+
"""
|
|
1503
|
+
Constructor.
|
|
1504
|
+
|
|
1505
|
+
:param name: Unique resource name assigned to the credential
|
|
1506
|
+
:param host: Host address of the server.
|
|
1507
|
+
:param port: Port number of the server.
|
|
1508
|
+
:param auth: Credentials to use for authentication.
|
|
1509
|
+
:param database: Name of the database to connect to
|
|
1510
|
+
:param enable_catalog: If set to true, this credential will
|
|
1511
|
+
be used to fetch catalog information.
|
|
1512
|
+
:param display_name: Human-readable name for the credential. This name is
|
|
1513
|
+
visible in the UI and does not need to be unique.
|
|
1514
|
+
:param ignore_changes: If set to true, changes to the resource will be ignored.
|
|
1515
|
+
"""
|
|
1516
|
+
super().__init__(
|
|
1517
|
+
name=name,
|
|
1518
|
+
display_name=display_name,
|
|
1519
|
+
ignore_changes=ignore_changes,
|
|
1520
|
+
__internal__=__internal__,
|
|
1521
|
+
)
|
|
1522
|
+
|
|
1523
|
+
self.host = host
|
|
1524
|
+
self.port = port
|
|
1525
|
+
self.database = database
|
|
1526
|
+
self.auth = auth
|
|
1527
|
+
self.enable_catalog = enable_catalog
|
|
1528
|
+
|
|
1529
|
+
def _immutable_fields(self) -> set[str]:
|
|
1530
|
+
return set({})
|
|
1531
|
+
|
|
1532
|
+
def _mutable_fields(self) -> set[str]:
|
|
1533
|
+
return {
|
|
1534
|
+
*super()._mutable_fields(),
|
|
1535
|
+
*{
|
|
1536
|
+
"host",
|
|
1537
|
+
"port",
|
|
1538
|
+
"database",
|
|
1539
|
+
"enable_catalog",
|
|
1540
|
+
},
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
def _secret_fields(self) -> set[str]:
|
|
1544
|
+
return set()
|
|
1545
|
+
|
|
1546
|
+
def _nested_objects(
|
|
1547
|
+
self,
|
|
1548
|
+
) -> dict[str, Optional["Diffable | list[Diffable]"] | None]:
|
|
1549
|
+
return {"auth": self.auth}
|
|
1550
|
+
|
|
1551
|
+
|
|
1311
1552
|
class TableauConnectedAppCredential(Credential):
|
|
1312
1553
|
"""
|
|
1313
1554
|
A credential resource that can be used to connect
|