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

wgtmac pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-cpp.git


The following commit(s) were added to refs/heads/main by this push:
     new 8f63dfd5 feat(io): expose FileIO configuration properties (#963)
8f63dfd5 is described below

commit 8f63dfd5d19dc91838a96e15d38c77414e548f7d
Author: Sreesh Maheshwar <[email protected]>
AuthorDate: Thu Nov 5 02:22:15 2026 +0000

    feat(io): expose FileIO configuration properties (#963)
---
 src/iceberg/arrow/s3/arrow_s3_file_io.cc  |  8 ++++++++
 src/iceberg/file_io.h                     | 10 ++++++++++
 src/iceberg/resolving_file_io.h           |  4 ++++
 src/iceberg/test/arrow_s3_file_io_test.cc | 12 ++++++++++++
 src/iceberg/test/rest_file_io_test.cc     | 12 ++++++++++++
 5 files changed, 46 insertions(+)

diff --git a/src/iceberg/arrow/s3/arrow_s3_file_io.cc 
b/src/iceberg/arrow/s3/arrow_s3_file_io.cc
index a38e8642..7ab182b8 100644
--- a/src/iceberg/arrow/s3/arrow_s3_file_io.cc
+++ b/src/iceberg/arrow/s3/arrow_s3_file_io.cc
@@ -454,6 +454,10 @@ class CredentialStore {
     return ResolveCredential(default_properties_, credential);
   }
 
+  const std::unordered_map<std::string, std::string>& default_properties() 
const {
+    return default_properties_;
+  }
+
   /// \brief Make `credentials` current, and `provider` too when one is given.
   void Install(std::vector<StorageCredential> credentials,
                std::optional<std::shared_ptr<StorageCredentialProvider>> 
provider) {
@@ -754,6 +758,10 @@ class ArrowS3FileIO final : public FileIO, public 
SupportsStorageCredentials {
       const std::vector<StorageCredential>& storage_credentials,
       std::shared_ptr<StorageCredentialProvider> provider) override;
 
+  const std::unordered_map<std::string, std::string>& properties() const 
override {
+    return credential_store_->default_properties();
+  }
+
   SupportsStorageCredentials* AsSupportsStorageCredentials() override { return 
this; }
 
  private:
diff --git a/src/iceberg/file_io.h b/src/iceberg/file_io.h
index 99d0588a..61e745a6 100644
--- a/src/iceberg/file_io.h
+++ b/src/iceberg/file_io.h
@@ -29,6 +29,7 @@
 #include <span>
 #include <string>
 #include <string_view>
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -181,6 +182,15 @@ class ICEBERG_EXPORT FileIO {
 
   /// \brief Return storage-credential support when implemented by this FileIO.
   virtual SupportsStorageCredentials* AsSupportsStorageCredentials() { return 
nullptr; }
+
+  /// \brief Return the configuration used to create this FileIO.
+  ///
+  /// The returned map may contain credentials. Callers must not log or expose 
it.
+  /// Implementations that do not expose their configuration return an empty 
map.
+  virtual const std::unordered_map<std::string, std::string>& properties() 
const {
+    static const std::unordered_map<std::string, std::string> kEmpty;
+    return kEmpty;
+  }
 };
 
 /// \brief Mix-in for FileIO implementations that route object paths to
diff --git a/src/iceberg/resolving_file_io.h b/src/iceberg/resolving_file_io.h
index 05e11eb8..70762c46 100644
--- a/src/iceberg/resolving_file_io.h
+++ b/src/iceberg/resolving_file_io.h
@@ -73,6 +73,10 @@ class ICEBERG_EXPORT ResolvingFileIO final : public FileIO,
       const std::vector<StorageCredential>& storage_credentials,
       std::shared_ptr<StorageCredentialProvider> provider) override;
 
+  const std::unordered_map<std::string, std::string>& properties() const 
override {
+    return properties_;
+  }
+
   SupportsStorageCredentials* AsSupportsStorageCredentials() override { return 
this; }
 
  private:
diff --git a/src/iceberg/test/arrow_s3_file_io_test.cc 
b/src/iceberg/test/arrow_s3_file_io_test.cc
index d0d61386..f7aa6ce6 100644
--- a/src/iceberg/test/arrow_s3_file_io_test.cc
+++ b/src/iceberg/test/arrow_s3_file_io_test.cc
@@ -452,6 +452,18 @@ TEST_F(ArrowS3FileIOTest, StoresCredentials) {
   EXPECT_EQ(credentialed->credentials(), credentials);
 }
 
+TEST_F(ArrowS3FileIOTest, PropertiesExposeFileIOConfiguration) {
+  auto result = MakeS3FileIO({{std::string(S3Properties::kClientRegion), 
"us-east-1"},
+                              {std::string(S3Properties::kAccessKeyId), "key"},
+                              {std::string(S3Properties::kSecretAccessKey), 
"secret"}});
+  ASSERT_THAT(result, IsOk());
+
+  const auto& properties = result.value()->properties();
+  EXPECT_EQ(properties.at(std::string(S3Properties::kClientRegion)), 
"us-east-1");
+  EXPECT_EQ(properties.at(std::string(S3Properties::kAccessKeyId)), "key");
+  EXPECT_EQ(properties.at(std::string(S3Properties::kSecretAccessKey)), 
"secret");
+}
+
 TEST_F(ArrowS3FileIOTest, SkipsNonS3CredentialPrefix) {
   auto result = MakeS3FileIO({});
   ASSERT_THAT(result, IsOk());
diff --git a/src/iceberg/test/rest_file_io_test.cc 
b/src/iceberg/test/rest_file_io_test.cc
index 31a027ab..9be2cdcf 100644
--- a/src/iceberg/test/rest_file_io_test.cc
+++ b/src/iceberg/test/rest_file_io_test.cc
@@ -115,6 +115,18 @@ TEST(RestFileIOTest, 
DefaultResolverDelegatesThroughRegistry) {
   EXPECT_THAT(result.value()->DeleteFile("rest-test://file"), IsOk());
 }
 
+TEST(RestFileIOTest, DefaultResolverExposesMergedProperties) {
+  auto result = MakeTableFileIO({{"catalog-only", "catalog"}, {"shared", 
"catalog"}},
+                                {{"table-only", "table"}, {"shared", "table"}},
+                                /*storage_credentials=*/{});
+  ASSERT_THAT(result, IsOk());
+
+  EXPECT_THAT(result.value()->properties(),
+              ::testing::UnorderedElementsAre(::testing::Pair("catalog-only", 
"catalog"),
+                                              ::testing::Pair("table-only", 
"table"),
+                                              ::testing::Pair("shared", 
"table")));
+}
+
 TEST(RestFileIOTest, MakeCatalogFileIOPassesThroughCustomImpl) {
   const std::string custom_impl = "com.mycompany.CustomFileIO";
   FileIORegistry::Register(

Reply via email to