datamasque-python 1.2.4__tar.gz → 1.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.
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/HISTORY.rst +26 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/PKG-INFO +1 -1
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/__init__.py +2 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/connection.py +59 -2
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/pyproject.toml +1 -1
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_connections.py +158 -6
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/uv.lock +1 -1
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/.editorconfig +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/.github/workflows/ci.yml +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/.github/workflows/release-testpypi.yml +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/.github/workflows/release.yml +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/.gitignore +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/.readthedocs.yaml +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/CONTRIBUTING.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/LICENSE +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/MANIFEST.in +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/Makefile +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/NOTICE +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/README.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/RELEASING.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/base.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/connections.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/discovery.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/discovery_config_libraries.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/discovery_configs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/dmclient.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/exceptions.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/files.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/ifm.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/license.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/__init__.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/data_selection.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/discovery.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/discovery_config.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/discovery_config_library.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/dm_instance.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/files.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/git.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/ifm.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/license.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/pagination.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/rg_config.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/ruleset.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/ruleset_library.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/runs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/safe_data_preview.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/status.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/table_reference.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/user.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/py.typed +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/rg_configs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/ruleset_libraries.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/rulesets.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/runs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/settings.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/spcs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/table_references.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/users.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/Makefile +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/client.models.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/client.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/conf.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/contributing.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/history.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/index.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/installation.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/make.bat +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/modules.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/readme.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/docs/usage.rst +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/__init__.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/conftest.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/helpers.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_base.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_discovery.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_discovery_config_libraries.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_discovery_configs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_files.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_ifm.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_license.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_pagination.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_rg_configs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_ruleset_library.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_rulesets.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_runs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_safe_data_preview.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_settings.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_spcs.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_table_references.py +0 -0
- {datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_users.py +0 -0
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
History
|
|
3
3
|
=======
|
|
4
4
|
|
|
5
|
+
1.3.0 (2026-09-04)
|
|
6
|
+
------------------
|
|
7
|
+
|
|
8
|
+
* Added ``CosmosDbConnectionConfig`` and the ``cosmosdb`` ``DatabaseType``, for Azure Cosmos DB.
|
|
9
|
+
It differs from ``MongoConnectionConfig`` by ``db_type`` and three defaults: ``port`` 10255,
|
|
10
|
+
``tls`` on, because Cosmos DB only accepts TLS connections, and ``retry_writes`` off, because
|
|
11
|
+
Cosmos DB rejects retryable inserts.
|
|
12
|
+
|
|
13
|
+
* ``DatabaseConnectionConfig`` now rejects the ``documentdb`` and ``cosmosdb`` database types with a
|
|
14
|
+
message naming the class to use, as it already did for MongoDB, DynamoDB, Snowflake and Databricks.
|
|
15
|
+
|
|
16
|
+
* The MongoDB serializer prunes ``tls`` and ``retry_writes`` against the concrete class's default
|
|
17
|
+
rather than MongoDB's, so a Cosmos DB config that sets either the other way now sends it instead
|
|
18
|
+
of leaving the server to apply its own default.
|
|
19
|
+
|
|
20
|
+
Requires server version 3.26.17
|
|
21
|
+
|
|
22
|
+
1.2.5 (2026-08-17)
|
|
23
|
+
------------------
|
|
24
|
+
|
|
25
|
+
* Added ``iam_role_arn`` to ``DatabaseConnectionConfig``: the IAM role DataMasque assumes to tag
|
|
26
|
+
the connection's AWS resource, for resources in another AWS account. Sent only for the engines
|
|
27
|
+
that can be an Amazon RDS instance, Aurora cluster or Redshift cluster.
|
|
28
|
+
|
|
29
|
+
Requires server version 3.26.16
|
|
30
|
+
|
|
5
31
|
1.2.4 (2026-08-12)
|
|
6
32
|
------------------
|
|
7
33
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: datamasque-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Official Python client for the DataMasque data-masking API.
|
|
5
5
|
Project-URL: Homepage, https://datamasque.com/
|
|
6
6
|
Project-URL: Documentation, https://datamasque-python.readthedocs.io/
|
|
@@ -31,6 +31,7 @@ from datamasque.client.models.connection import (
|
|
|
31
31
|
AzureConnectionConfig,
|
|
32
32
|
ConnectionConfig,
|
|
33
33
|
ConnectionId,
|
|
34
|
+
CosmosDbConnectionConfig,
|
|
34
35
|
DatabaseConnectionConfig,
|
|
35
36
|
DatabaseType,
|
|
36
37
|
DatabricksConnectionConfig,
|
|
@@ -203,6 +204,7 @@ __all__ = [
|
|
|
203
204
|
"DiscoveryConfigNotFoundError",
|
|
204
205
|
"DiscoveryConfigType",
|
|
205
206
|
"DiscoveryMatch",
|
|
207
|
+
"CosmosDbConnectionConfig",
|
|
206
208
|
"DocumentDbConnectionConfig",
|
|
207
209
|
"DynamoConnectionConfig",
|
|
208
210
|
"FailedToStartError",
|
|
@@ -45,6 +45,7 @@ class DatabaseType(Enum):
|
|
|
45
45
|
snowflake = "snowflake"
|
|
46
46
|
mongodb = "mongodb"
|
|
47
47
|
documentdb = "documentdb"
|
|
48
|
+
cosmosdb = "cosmosdb"
|
|
48
49
|
databricks_lakebase = "databricks_lakebase"
|
|
49
50
|
databricks = "databricks"
|
|
50
51
|
informix = "informix"
|
|
@@ -184,8 +185,11 @@ class MongoConnectionConfig(ConnectionConfig):
|
|
|
184
185
|
password = d.pop("password", None)
|
|
185
186
|
if password:
|
|
186
187
|
d["dbpassword"] = password
|
|
188
|
+
# `tls` and `retry_writes` are pruned against this class's own default, not MongoDB's:
|
|
189
|
+
# the subclasses invert them, so a hardcoded comparison would drop the very value the
|
|
190
|
+
# caller set and let the server apply its default instead.
|
|
191
|
+
defaults = type(self).model_fields
|
|
187
192
|
if not d.get("tls"):
|
|
188
|
-
d.pop("tls", None)
|
|
189
193
|
d.pop("tls_ca_file", None)
|
|
190
194
|
d.pop("tls_allow_invalid_certificates", None)
|
|
191
195
|
else:
|
|
@@ -193,9 +197,11 @@ class MongoConnectionConfig(ConnectionConfig):
|
|
|
193
197
|
d.pop("tls_ca_file", None)
|
|
194
198
|
if not d.get("tls_allow_invalid_certificates"):
|
|
195
199
|
d.pop("tls_allow_invalid_certificates", None)
|
|
200
|
+
if d.get("tls") == defaults["tls"].default:
|
|
201
|
+
d.pop("tls", None)
|
|
196
202
|
if not d.get("direct_connection"):
|
|
197
203
|
d.pop("direct_connection", None)
|
|
198
|
-
if d.get("retry_writes"
|
|
204
|
+
if d.get("retry_writes") == defaults["retry_writes"].default:
|
|
199
205
|
d.pop("retry_writes", None)
|
|
200
206
|
if not d.get("replica_set"):
|
|
201
207
|
d.pop("replica_set", None)
|
|
@@ -229,6 +235,29 @@ class DocumentDbConnectionConfig(MongoConnectionConfig):
|
|
|
229
235
|
return DatabaseType.documentdb
|
|
230
236
|
|
|
231
237
|
|
|
238
|
+
class CosmosDbConnectionConfig(MongoConnectionConfig):
|
|
239
|
+
"""
|
|
240
|
+
Connection configuration for an Azure Cosmos DB account.
|
|
241
|
+
|
|
242
|
+
Cosmos DB listens on 10255, only accepts TLS connections and rejects retryable inserts, so it
|
|
243
|
+
differs from `MongoConnectionConfig` by `db_type`/`database_type` and those three defaults.
|
|
244
|
+
|
|
245
|
+
They are defaults, not constraints. Setting one the other way sends it to the server: with
|
|
246
|
+
retryable writes on, masking still runs (it only updates) but the run-history insert is
|
|
247
|
+
rejected, so the run is not recorded.
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
# Narrowing the inherited Literal is a deliberate Pydantic discriminator override.
|
|
251
|
+
db_type: Literal["cosmosdb"] = "cosmosdb" # type: ignore[assignment]
|
|
252
|
+
port: int = 10255
|
|
253
|
+
tls: bool = True
|
|
254
|
+
retry_writes: bool = False
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def database_type(self) -> DatabaseType:
|
|
258
|
+
return DatabaseType.cosmosdb
|
|
259
|
+
|
|
260
|
+
|
|
232
261
|
class SnowflakeConnectionConfig(ConnectionConfig):
|
|
233
262
|
"""
|
|
234
263
|
Connection configuration for a Snowflake database.
|
|
@@ -289,6 +318,22 @@ class SnowflakeConnectionConfig(ConnectionConfig):
|
|
|
289
318
|
return data
|
|
290
319
|
|
|
291
320
|
|
|
321
|
+
# Engines that can sit behind an Amazon RDS, Aurora or Redshift endpoint, and so can carry a role
|
|
322
|
+
# for DataMasque to assume when tagging the resource. Aurora needs no entry of its own: it uses
|
|
323
|
+
# these same engines with a cluster endpoint.
|
|
324
|
+
_AWS_TAGGABLE_DATABASE_TYPES = frozenset(
|
|
325
|
+
{
|
|
326
|
+
DatabaseType.postgres,
|
|
327
|
+
DatabaseType.mysql,
|
|
328
|
+
DatabaseType.mariadb,
|
|
329
|
+
DatabaseType.oracle,
|
|
330
|
+
DatabaseType.mssql,
|
|
331
|
+
DatabaseType.db2_luw,
|
|
332
|
+
DatabaseType.redshift,
|
|
333
|
+
}
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
|
|
292
337
|
class DatabaseConnectionConfig(ConnectionConfig):
|
|
293
338
|
"""
|
|
294
339
|
Connection configuration for a SQL database.
|
|
@@ -309,6 +354,11 @@ class DatabaseConnectionConfig(ConnectionConfig):
|
|
|
309
354
|
is_read_only: bool = False
|
|
310
355
|
s3_bucket_name: Optional[str] = None
|
|
311
356
|
s3_redshift_iam_role: Optional[str] = None
|
|
357
|
+
# An IAM role for DataMasque to assume when tagging this database's AWS resource after a run.
|
|
358
|
+
# Only the engines in `_AWS_TAGGABLE_DATABASE_TYPES` can be an RDS instance, Aurora cluster or
|
|
359
|
+
# Redshift cluster, so it is pruned for the rest. Distinct from `s3_redshift_iam_role`, which is
|
|
360
|
+
# the role the Redshift cluster itself uses to reach S3.
|
|
361
|
+
iam_role_arn: Optional[str] = None
|
|
312
362
|
|
|
313
363
|
@model_validator(mode="after")
|
|
314
364
|
def _reject_special_engines(self) -> "DatabaseConnectionConfig":
|
|
@@ -318,6 +368,10 @@ class DatabaseConnectionConfig(ConnectionConfig):
|
|
|
318
368
|
raise ValueError("For Snowflake, use the SnowflakeConnectionConfig class instead")
|
|
319
369
|
if self.database_type is DatabaseType.mongodb:
|
|
320
370
|
raise ValueError("For MongoDB, use the MongoConnectionConfig class instead")
|
|
371
|
+
if self.database_type is DatabaseType.documentdb:
|
|
372
|
+
raise ValueError("For AWS DocumentDB, use the DocumentDbConnectionConfig class instead")
|
|
373
|
+
if self.database_type is DatabaseType.cosmosdb:
|
|
374
|
+
raise ValueError("For Azure Cosmos DB, use the CosmosDbConnectionConfig class instead")
|
|
321
375
|
if self.database_type is DatabaseType.databricks:
|
|
322
376
|
raise ValueError("For Databricks SQL Warehouse, use the DatabricksConnectionConfig class instead")
|
|
323
377
|
return self
|
|
@@ -348,6 +402,8 @@ class DatabaseConnectionConfig(ConnectionConfig):
|
|
|
348
402
|
if db_type is not DatabaseType.redshift:
|
|
349
403
|
d.pop("s3_bucket_name", None)
|
|
350
404
|
d.pop("s3_redshift_iam_role", None)
|
|
405
|
+
if db_type not in _AWS_TAGGABLE_DATABASE_TYPES:
|
|
406
|
+
d.pop("iam_role_arn", None)
|
|
351
407
|
if not d.get("engine_options"):
|
|
352
408
|
d.pop("engine_options", None)
|
|
353
409
|
return d
|
|
@@ -467,6 +523,7 @@ DB_TYPE_MAP: dict[str, type[ConnectionConfig]] = {
|
|
|
467
523
|
DatabaseType.dynamodb.value: DynamoConnectionConfig,
|
|
468
524
|
DatabaseType.mongodb.value: MongoConnectionConfig,
|
|
469
525
|
DatabaseType.documentdb.value: DocumentDbConnectionConfig,
|
|
526
|
+
DatabaseType.cosmosdb.value: CosmosDbConnectionConfig,
|
|
470
527
|
DatabaseType.snowflake.value: SnowflakeConnectionConfig,
|
|
471
528
|
DatabaseType.mssql_linked.value: MssqlLinkedServerConnectionConfig,
|
|
472
529
|
DatabaseType.databricks.value: DatabricksConnectionConfig,
|
|
@@ -7,6 +7,7 @@ from datamasque.client.exceptions import DataMasqueApiError, DataMasqueException
|
|
|
7
7
|
from datamasque.client.models.connection import (
|
|
8
8
|
AzureConnectionConfig,
|
|
9
9
|
ConnectionId,
|
|
10
|
+
CosmosDbConnectionConfig,
|
|
10
11
|
DatabaseConnectionConfig,
|
|
11
12
|
DatabaseType,
|
|
12
13
|
DatabricksConnectionConfig,
|
|
@@ -1360,17 +1361,85 @@ def test_connection_config_dispatch_picks_documentdb_subclass():
|
|
|
1360
1361
|
assert conn.database_type is DatabaseType.documentdb
|
|
1361
1362
|
|
|
1362
1363
|
|
|
1363
|
-
def
|
|
1364
|
-
"""
|
|
1365
|
-
|
|
1364
|
+
def _cosmosdb_connection(**overrides) -> CosmosDbConnectionConfig:
|
|
1365
|
+
"""Build a Cosmos DB config, leaving the port to the connection type's own default."""
|
|
1366
|
+
return CosmosDbConnectionConfig(
|
|
1367
|
+
name="cosmos",
|
|
1368
|
+
host="dtq-cosmos.mongo.cosmos.azure.com",
|
|
1369
|
+
database="people",
|
|
1370
|
+
user="dtq-cosmos",
|
|
1371
|
+
password="hunter2",
|
|
1372
|
+
**overrides,
|
|
1373
|
+
)
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
def test_cosmosdb_connection_defaults_port_tls_and_retry_writes():
|
|
1377
|
+
"""
|
|
1378
|
+
Cosmos DB listens on 10255, only accepts TLS connections and rejects retryable writes.
|
|
1379
|
+
|
|
1380
|
+
The config carries all three as defaults. `tls` and `retry_writes` are omitted from the payload
|
|
1381
|
+
because the server defaults the same way for this connection type; the port is always sent.
|
|
1382
|
+
"""
|
|
1383
|
+
conn = _cosmosdb_connection()
|
|
1384
|
+
d = conn.model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
1385
|
+
assert d["db_type"] == "cosmosdb"
|
|
1386
|
+
assert d["mask_type"] == "database"
|
|
1387
|
+
assert conn.port == 10255
|
|
1388
|
+
assert d["port"] == 10255
|
|
1389
|
+
assert conn.tls is True
|
|
1390
|
+
assert conn.retry_writes is False
|
|
1391
|
+
assert "tls" not in d
|
|
1392
|
+
assert "retry_writes" not in d
|
|
1393
|
+
assert conn.database_type is DatabaseType.cosmosdb
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
def test_cosmosdb_connection_sends_values_that_differ_from_its_own_defaults():
|
|
1397
|
+
"""
|
|
1398
|
+
The Mongo serializer prunes a field whose value matches the default the server would apply.
|
|
1399
|
+
|
|
1400
|
+
Cosmos DB inverts two of MongoDB's defaults, so pruning against MongoDB's would drop exactly
|
|
1401
|
+
the value the caller set and leave the server applying the opposite.
|
|
1402
|
+
"""
|
|
1403
|
+
d = _cosmosdb_connection(tls=False, retry_writes=True).model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
1404
|
+
assert d["tls"] is False
|
|
1405
|
+
assert d["retry_writes"] is True
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
def test_connection_config_dispatch_picks_cosmosdb_subclass():
|
|
1409
|
+
payload = {
|
|
1410
|
+
"id": "cosmos-id-1",
|
|
1411
|
+
"name": "cosmos",
|
|
1412
|
+
"mask_type": "database",
|
|
1413
|
+
"db_type": "cosmosdb",
|
|
1414
|
+
"host": "dtq-cosmos.mongo.cosmos.azure.com",
|
|
1415
|
+
"database": "people",
|
|
1416
|
+
}
|
|
1417
|
+
conn = validate_connection(payload)
|
|
1418
|
+
assert isinstance(conn, CosmosDbConnectionConfig)
|
|
1419
|
+
assert conn.database_type is DatabaseType.cosmosdb
|
|
1420
|
+
|
|
1421
|
+
|
|
1422
|
+
@pytest.mark.parametrize(
|
|
1423
|
+
("database_type", "message"),
|
|
1424
|
+
[
|
|
1425
|
+
(DatabaseType.mongodb, "For MongoDB"),
|
|
1426
|
+
(DatabaseType.documentdb, "For AWS DocumentDB"),
|
|
1427
|
+
(DatabaseType.cosmosdb, "For Azure Cosmos DB"),
|
|
1428
|
+
],
|
|
1429
|
+
)
|
|
1430
|
+
def test_database_connection_config_rejects_document_store_database_types(
|
|
1431
|
+
database_type: DatabaseType, message: str
|
|
1432
|
+
) -> None:
|
|
1433
|
+
"""`DatabaseConnectionConfig` is for SQL engines; each document store has its own class."""
|
|
1434
|
+
with pytest.raises(ValueError, match=message):
|
|
1366
1435
|
DatabaseConnectionConfig(
|
|
1367
|
-
name="
|
|
1368
|
-
host="
|
|
1436
|
+
name="doc-store",
|
|
1437
|
+
host="doc-store.example",
|
|
1369
1438
|
port=27017,
|
|
1370
1439
|
database="people",
|
|
1371
1440
|
user="alice",
|
|
1372
1441
|
password="hunter2",
|
|
1373
|
-
database_type=
|
|
1442
|
+
database_type=database_type,
|
|
1374
1443
|
)
|
|
1375
1444
|
|
|
1376
1445
|
|
|
@@ -1400,3 +1469,86 @@ def test_create_or_update_mongo_connection(client):
|
|
|
1400
1469
|
assert sent["db_type"] == "mongodb"
|
|
1401
1470
|
assert sent["dbpassword"] == "hunter2"
|
|
1402
1471
|
assert sent["replica_set"] == "rs0"
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
def _database_connection(database_type: DatabaseType, **extra) -> DatabaseConnectionConfig:
|
|
1475
|
+
return DatabaseConnectionConfig(
|
|
1476
|
+
name="conn",
|
|
1477
|
+
host="mydb.abc123.ap-southeast-2.rds.amazonaws.com",
|
|
1478
|
+
port=5432,
|
|
1479
|
+
database="db",
|
|
1480
|
+
user="user",
|
|
1481
|
+
password="secret",
|
|
1482
|
+
database_type=database_type,
|
|
1483
|
+
**extra,
|
|
1484
|
+
)
|
|
1485
|
+
|
|
1486
|
+
|
|
1487
|
+
@pytest.mark.parametrize(
|
|
1488
|
+
"database_type",
|
|
1489
|
+
[
|
|
1490
|
+
DatabaseType.postgres,
|
|
1491
|
+
DatabaseType.mysql,
|
|
1492
|
+
DatabaseType.mariadb,
|
|
1493
|
+
DatabaseType.oracle,
|
|
1494
|
+
DatabaseType.mssql,
|
|
1495
|
+
DatabaseType.db2_luw,
|
|
1496
|
+
DatabaseType.redshift,
|
|
1497
|
+
],
|
|
1498
|
+
)
|
|
1499
|
+
def test_database_connection_sends_tagging_iam_role_for_aws_hosted_engines(database_type):
|
|
1500
|
+
"""The engines that can sit behind an RDS, Aurora or Redshift endpoint can carry a tagging role."""
|
|
1501
|
+
extra = (
|
|
1502
|
+
{"s3_bucket_name": "bucket", "s3_redshift_iam_role": "arn:aws:iam::123456789012:role/redshift-s3"}
|
|
1503
|
+
if database_type is DatabaseType.redshift
|
|
1504
|
+
else {}
|
|
1505
|
+
)
|
|
1506
|
+
conn = _database_connection(database_type, iam_role_arn="arn:aws:iam::119836602066:role/tagger", **extra)
|
|
1507
|
+
|
|
1508
|
+
api_dict = conn.model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
1509
|
+
|
|
1510
|
+
assert api_dict["iam_role_arn"] == "arn:aws:iam::119836602066:role/tagger"
|
|
1511
|
+
|
|
1512
|
+
|
|
1513
|
+
@pytest.mark.parametrize(
|
|
1514
|
+
"database_type",
|
|
1515
|
+
[
|
|
1516
|
+
DatabaseType.db2i,
|
|
1517
|
+
DatabaseType.informix,
|
|
1518
|
+
DatabaseType.saphana,
|
|
1519
|
+
# The two worth documenting rather than merely covering. `mssql_linked` inherits the field
|
|
1520
|
+
# through `MssqlLinkedServerConnectionConfig` and is excluded only by its own enum value;
|
|
1521
|
+
# `databricks_lakebase` is AWS-hosted, so it reads like an omission from the taggable set
|
|
1522
|
+
# until you know it presents no endpoint tagging can act on.
|
|
1523
|
+
DatabaseType.mssql_linked,
|
|
1524
|
+
DatabaseType.databricks_lakebase,
|
|
1525
|
+
],
|
|
1526
|
+
)
|
|
1527
|
+
def test_database_connection_omits_tagging_iam_role_for_engines_that_cannot_be_aws_resources(database_type):
|
|
1528
|
+
"""Mirrors how `s3_redshift_iam_role` is pruned: the server has no such field on these engines."""
|
|
1529
|
+
conn = _database_connection(database_type, iam_role_arn="arn:aws:iam::119836602066:role/tagger")
|
|
1530
|
+
|
|
1531
|
+
api_dict = conn.model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
1532
|
+
|
|
1533
|
+
assert "iam_role_arn" not in api_dict
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
def test_database_connection_omits_tagging_iam_role_when_unset():
|
|
1537
|
+
conn = _database_connection(DatabaseType.postgres)
|
|
1538
|
+
|
|
1539
|
+
assert "iam_role_arn" not in conn.model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
def test_redshift_connection_keeps_its_cluster_s3_role_separate_from_its_tagging_role():
|
|
1543
|
+
"""Two ARNs with different meanings: the cluster's own S3 access, and the role DataMasque assumes to tag."""
|
|
1544
|
+
conn = _database_connection(
|
|
1545
|
+
DatabaseType.redshift,
|
|
1546
|
+
s3_bucket_name="bucket",
|
|
1547
|
+
s3_redshift_iam_role="arn:aws:iam::123456789012:role/redshift-s3",
|
|
1548
|
+
iam_role_arn="arn:aws:iam::119836602066:role/tagger",
|
|
1549
|
+
)
|
|
1550
|
+
|
|
1551
|
+
api_dict = conn.model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
1552
|
+
|
|
1553
|
+
assert api_dict["s3_redshift_iam_role"] == "arn:aws:iam::123456789012:role/redshift-s3"
|
|
1554
|
+
assert api_dict["iam_role_arn"] == "arn:aws:iam::119836602066:role/tagger"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/discovery_config_libraries.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/data_selection.py
RENAMED
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/discovery_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/ruleset_library.py
RENAMED
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/safe_data_preview.py
RENAMED
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.4 → datamasque_python-1.3.0}/datamasque/client/models/table_reference.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.4 → datamasque_python-1.3.0}/tests/test_discovery_config_libraries.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|