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(