You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polaris.apache.org by yz...@apache.org on 2026/07/29 05:55:56 UTC

(polaris) branch main updated: Python CLI: support --no-sts and --no-kms in catalogs update (#5166)

This is an automated email from the ASF dual-hosted git repository.

MonkeyCanCode pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git


The following commit(s) were added to refs/heads/main by this push:
     new 67df6f4836 Python CLI: support --no-sts and --no-kms in catalogs update (#5166)
67df6f4836 is described below

commit 67df6f48365c0b9120f476a1f0c782b31b9ba8f9
Author: Yalın Doğu Şahin <10...@users.noreply.github.com>
AuthorDate: Wed Jul 29 07:55:51 2026 +0200

    Python CLI: support --no-sts and --no-kms in catalogs update (#5166)
    
    * Python CLI: support --no-sts and --no-kms in catalogs update
    
    * Extract _require_s3 helper for S3-only update flags
    
    ---------
    
    Co-authored-by: yalin.sahin <ya...@tradition.ch>
---
 CHANGELOG.md                                       |  1 +
 .../python/apache_polaris/cli/command/catalogs.py  | 26 ++++++---
 .../apache_polaris/cli/options/option_tree.py      | 12 +++++
 client/python/tests/test_catalogs_command.py       | 61 ++++++++++++++++++++++
 .../in-dev/unreleased/command-line-interface.md    |  4 ++
 5 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63b17e1ffc..092a031f2c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -77,6 +77,7 @@ request adding CHANGELOG notes for breaking (!) changes and possibly other secti
 - Added an OpenTelemetry event listener for emitting Polaris audit events as OpenTelemetry log records.
 - Added optional `sessionPolicy` field to `SigV4AuthenticationParameters` for catalog federation. When set, the IAM session policy JSON is attached to the STS AssumeRole request, allowing administrators to restrict vended credentials to only the required AWS services and actions (Principle of Least Privilege).
 - Python CLI: added `--scheme` to specify URL scheme
+- Python CLI: `catalogs update` now supports `--no-sts` and `--no-kms` to toggle STS/KMS availability on an existing S3 catalog. Previously these were only settable at `catalogs create` time.
 - Added opt-in idempotency for `createTable` and `updateTable` in the Iceberg REST catalog. When enabled via `polaris.idempotency.enabled=true` (default `false`), a client-supplied `Idempotency-Key` header is embedded into the table entity and committed in the same transaction as the operation; a retry carrying the same key within the TTL window (`polaris.idempotency.ttl`, default `PT5M`) replays the original success instead of failing — with `AlreadyExists` for `createTable`, or with `C [...]
 
 ### Changes
diff --git a/client/python/apache_polaris/cli/command/catalogs.py b/client/python/apache_polaris/cli/command/catalogs.py
index 1a7c5f1eaf..6d4d261147 100644
--- a/client/python/apache_polaris/cli/command/catalogs.py
+++ b/client/python/apache_polaris/cli/command/catalogs.py
@@ -267,6 +267,8 @@ class CatalogsCommand(Command):
             or self.current_kms_key
             or self.allowed_kms_keys
             or self.path_style_access
+            or self.sts_unavailable
+            or self.kms_unavailable
         )
 
     def _has_azure_storage_info(self) -> bool:
@@ -280,6 +282,14 @@ class CatalogsCommand(Command):
     def _has_gcs_storage_info(self) -> bool:
         return bool(self.service_account)
 
+    @staticmethod
+    def _require_s3(storage_info: StorageConfigInfo, flag: str) -> None:
+        # Note: We have to lowercase the returned value because the server enum
+        # is uppercase but we defined the StorageType enums as lowercase.
+        storage_type = storage_info.storage_type
+        if storage_type.lower() != StorageType.S3.value:
+            raise CliError(f"{flag} requires S3 storage_type, got: {storage_type}")
+
     def _build_storage_config_info(self) -> Optional[StorageConfigInfo]:
         config = None
         if self.storage_type == StorageType.S3.value:
@@ -501,15 +511,17 @@ class CatalogsCommand(Command):
                     )
 
                 if self.region:
-                    # Note: We have to lowercase the returned value because the server enum
-                    # is uppercase but we defined the StorageType enums as lowercase.
-                    storage_type = updated_storage_info.storage_type
-                    if storage_type.lower() != StorageType.S3.value:
-                        raise CliError(
-                            f"--region requires S3 storage_type, got: {storage_type}"
-                        )
+                    self._require_s3(updated_storage_info, "--region")
                     updated_storage_info.region = self.region
 
+                if self.sts_unavailable:
+                    self._require_s3(updated_storage_info, "--no-sts")
+                    updated_storage_info.sts_unavailable = self.sts_unavailable
+
+                if self.kms_unavailable:
+                    self._require_s3(updated_storage_info, "--no-kms")
+                    updated_storage_info.kms_unavailable = self.kms_unavailable
+
                 request = UpdateCatalogRequest(
                     current_entity_version=catalog.entity_version,
                     properties=catalog.properties.to_dict(),
diff --git a/client/python/apache_polaris/cli/options/option_tree.py b/client/python/apache_polaris/cli/options/option_tree.py
index d8f6b6ae61..83d38c119f 100644
--- a/client/python/apache_polaris/cli/options/option_tree.py
+++ b/client/python/apache_polaris/cli/options/option_tree.py
@@ -398,6 +398,18 @@ class OptionTree:
                             Hints.S3_REGION,
                             group="AWS S3 Storage Options",
                         ),
+                        Argument(
+                            Arguments.STS_UNAVAILABLE,
+                            bool,
+                            Hints.S3_STS_UNAVAILABLE,
+                            group="AWS S3 Storage Options",
+                        ),
+                        Argument(
+                            Arguments.KMS_UNAVAILABLE,
+                            bool,
+                            Hints.S3_KMS_UNAVAILABLE,
+                            group="AWS S3 Storage Options",
+                        ),
                         Argument(
                             Arguments.SET_PROPERTY,
                             str,
diff --git a/client/python/tests/test_catalogs_command.py b/client/python/tests/test_catalogs_command.py
index 2fcb6b6d10..5c040eadcf 100644
--- a/client/python/tests/test_catalogs_command.py
+++ b/client/python/tests/test_catalogs_command.py
@@ -25,6 +25,7 @@ from apache_polaris.sdk.management import (
     PolarisCatalog,
     CatalogProperties,
     AwsStorageConfigInfo,
+    StorageConfigInfo,
 )
 
 
@@ -464,6 +465,66 @@ class TestCatalogsCommand(CLITestBase):
         self.mock_execute(mock_client, ["catalogs", "get", "foo"])
         mock_client.get_catalog.assert_called_with("foo")
 
+    def test_catalog_update_s3_options(self) -> None:
+        mock_client = self.build_mock_client()
+        mock_client.get_catalog.return_value = PolarisCatalog(
+            type="INTERNAL",
+            name="s3-catalog",
+            entity_version=1,
+            properties=CatalogProperties(
+                default_base_location="s3://bucket/path", additional_properties={}
+            ),
+            storage_config_info=AwsStorageConfigInfo(
+                storage_type="S3", allowed_locations=[]
+            ),
+        )
+        self.mock_execute(
+            mock_client,
+            ["catalogs", "update", "s3-catalog", "--no-sts", "--no-kms"],
+        )
+        call_args = mock_client.update_catalog.call_args[0][1]
+        self.assertTrue(call_args.storage_config_info.sts_unavailable)
+        self.assertTrue(call_args.storage_config_info.kms_unavailable)
+
+        # --no-kms alone (without any other AWS storage option) must still be applied
+        mock_client.get_catalog.return_value = PolarisCatalog(
+            type="INTERNAL",
+            name="s3-catalog",
+            entity_version=1,
+            properties=CatalogProperties(
+                default_base_location="s3://bucket/path", additional_properties={}
+            ),
+            storage_config_info=AwsStorageConfigInfo(
+                storage_type="S3", allowed_locations=[]
+            ),
+        )
+        self.mock_execute(
+            mock_client,
+            ["catalogs", "update", "s3-catalog", "--no-kms"],
+        )
+        call_args = mock_client.update_catalog.call_args[0][1]
+        self.assertTrue(call_args.storage_config_info.kms_unavailable)
+
+        # --no-kms against a non-S3 catalog should raise
+        mock_client.get_catalog.return_value = PolarisCatalog(
+            type="INTERNAL",
+            name="gcs-catalog",
+            entity_version=1,
+            properties=CatalogProperties(
+                default_base_location="gs://bucket/path", additional_properties={}
+            ),
+            storage_config_info=StorageConfigInfo(
+                storage_type="GCS", allowed_locations=[]
+            ),
+        )
+        self.check_exception(
+            lambda: self.mock_execute(
+                mock_client,
+                ["catalogs", "update", "gcs-catalog", "--no-kms"],
+            ),
+            "--no-kms requires S3 storage_type",
+        )
+
     def test_catalog_list(self) -> None:
         mock_client = self.build_mock_client()
         mock_client.list_catalogs.return_values.catalogs = []
diff --git a/site/content/in-dev/unreleased/command-line-interface.md b/site/content/in-dev/unreleased/command-line-interface.md
index 5cbb58ce6b..d15af03509 100644
--- a/site/content/in-dev/unreleased/command-line-interface.md
+++ b/site/content/in-dev/unreleased/command-line-interface.md
@@ -351,6 +351,8 @@ Command Options:
 
 AWS S3 Storage Options:
   --region REGION                                The region to use when connecting to S3
+  --no-sts                                       Indicates that Polaris should not use STS (e.g. if STS is not available)
+  --no-kms                                       Indicates that Polaris should not use KMS (e.g. if KMS is not available)
 ```
 
 ##### Examples
@@ -359,6 +361,8 @@ AWS S3 Storage Options:
 polaris catalogs update --set-property tag=new_value my_catalog
 
 polaris catalogs update --default-base-location s3://new-bucket/my_data my_catalog
+
+polaris catalogs update --no-kms my_catalog
 ```
 
 ### Principals