|
15 | 15 | # specific language governing permissions and limitations |
16 | 16 | # under the License. |
17 | 17 | # pylint:disable=redefined-outer-name |
| 18 | +import base64 |
18 | 19 | import json |
19 | 20 | import uuid |
20 | 21 | from copy import copy |
|
49 | 50 | TableIdentifier, |
50 | 51 | _match_deletes_to_data_file, |
51 | 52 | ) |
| 53 | +from pyiceberg.table.encryption import EncryptedKey |
52 | 54 | from pyiceberg.table.metadata import INITIAL_SEQUENCE_NUMBER, TableMetadataUtil, TableMetadataV2, _generate_snapshot_id |
53 | 55 | from pyiceberg.table.refs import SnapshotRef |
54 | 56 | from pyiceberg.table.snapshots import ( |
|
66 | 68 | ) |
67 | 69 | from pyiceberg.table.statistics import BlobMetadata, StatisticsFile |
68 | 70 | from pyiceberg.table.update import ( |
| 71 | + AddEncryptedKeyUpdate, |
69 | 72 | AddSnapshotUpdate, |
70 | 73 | AddSortOrderUpdate, |
71 | 74 | AssertCreate, |
@@ -1345,3 +1348,63 @@ def test_remove_statistics_update(table_v2_with_statistics: Table) -> None: |
1345 | 1348 | table_v2_with_statistics.metadata, |
1346 | 1349 | (RemoveStatisticsUpdate(snapshot_id=123456789),), |
1347 | 1350 | ) |
| 1351 | + |
| 1352 | +def test_add_encryption_key(table_v3: Table) -> None: |
| 1353 | + update = AddEncryptedKeyUpdate( |
| 1354 | + key=EncryptedKey( |
| 1355 | + key_id="test", |
| 1356 | + encrypted_key_metadata=base64.b64encode("hello".encode('utf-8')) |
| 1357 | + ) |
| 1358 | + ) |
| 1359 | + |
| 1360 | + expected = """ |
| 1361 | + { |
| 1362 | + "key-id": "test", |
| 1363 | + "encrypted-key-metadata": "aGVsbG8=" |
| 1364 | + }""" |
| 1365 | + |
| 1366 | + assert table_v3.metadata.encryption_keys == [] |
| 1367 | + add_metadata = update_table_metadata(table_v3.metadata, (update,)) |
| 1368 | + assert len(add_metadata.encryption_keys) == 1 |
| 1369 | + |
| 1370 | + assert json.loads(add_metadata.encryption_keys[0].model_dump_json()) == json.loads(expected) |
| 1371 | + |
| 1372 | +def test_remove_encryption_key(table_v3: Table) -> None: |
| 1373 | + update_add = AddEncryptedKeyUpdate( |
| 1374 | + key=EncryptedKey( |
| 1375 | + key_id="test", |
| 1376 | + encrypted_key_metadata=base64.b64encode("hello".encode('utf-8')) |
| 1377 | + ) |
| 1378 | + ) |
| 1379 | + add_metadata = update_table_metadata(table_v3.metadata, (update_add,)) |
| 1380 | + assert len(add_metadata.encryption_keys) == 1 |
| 1381 | + |
| 1382 | + update_remove = RemoveEncryptedKeyUpdate(key_id="test") |
| 1383 | + remove_metadata = update_table_metadata(add_metadata, (update_remove,)) |
| 1384 | + assert len(remove_metadata.encryption_keys) == 0 |
| 1385 | + |
| 1386 | + |
| 1387 | +def test_remove_non_existent_encryption_key(table_v3: Table) -> None: |
| 1388 | + update_add = AddEncryptedKeyUpdate( |
| 1389 | + key=EncryptedKey( |
| 1390 | + key_id="test", |
| 1391 | + encrypted_key_metadata=base64.b64encode("hello".encode('utf-8')) |
| 1392 | + ) |
| 1393 | + ) |
| 1394 | + add_metadata = update_table_metadata(table_v3.metadata, (update_add,)) |
| 1395 | + assert len(add_metadata.encryption_keys) == 1 |
| 1396 | + |
| 1397 | + update_remove = RemoveEncryptedKeyUpdate(key_id="non_existent_key") |
| 1398 | + remove_metadata = update_table_metadata(add_metadata, (update_remove,)) |
| 1399 | + assert len(remove_metadata.encryption_keys) == 1 # Should be a no-op |
| 1400 | + |
| 1401 | + |
| 1402 | +def test_add_remove_encryption_key_v2_table(table_v2: Table) -> None: |
| 1403 | + update_add = AddEncryptedKeyUpdate( |
| 1404 | + key=EncryptedKey( |
| 1405 | + key_id="test_v2", |
| 1406 | + encrypted_key_metadata=base64.b64encode("hello_v2".encode('utf-8')) |
| 1407 | + ) |
| 1408 | + ) |
| 1409 | + with pytest.raises(ValueError, match=r"Cannot add encryption keys from Iceberg v1 or v2 table"): |
| 1410 | + update_table_metadata(table_v2.metadata, (update_add,)) |
0 commit comments