XJDKC commented on code in PR #724: URL: https://github.com/apache/polaris/pull/724#discussion_r1930038496
########## service/common/src/main/java/org/apache/polaris/service/catalog/io/DefaultFileIOFactory.java: ########## @@ -18,19 +18,112 @@ */ package org.apache.polaris.service.catalog.io; +import com.google.common.annotations.VisibleForTesting; import io.smallrye.common.annotation.Identifier; +import jakarta.annotation.Nonnull; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import java.util.HashMap; import java.util.Map; +import java.util.Optional; +import java.util.Set; import org.apache.hadoop.conf.Configuration; import org.apache.iceberg.CatalogUtil; +import org.apache.iceberg.catalog.TableIdentifier; import org.apache.iceberg.io.FileIO; +import org.apache.polaris.core.PolarisConfigurationStore; +import org.apache.polaris.core.context.RealmId; +import org.apache.polaris.core.entity.PolarisEntity; +import org.apache.polaris.core.persistence.MetaStoreManagerFactory; +import org.apache.polaris.core.persistence.PolarisEntityManager; +import org.apache.polaris.core.persistence.PolarisMetaStoreSession; +import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper; +import org.apache.polaris.core.storage.PolarisCredentialVendor; +import org.apache.polaris.core.storage.PolarisStorageActions; +import org.apache.polaris.service.config.RealmEntityManagerFactory; -/** A simple FileIOFactory implementation that defers all the work to the Iceberg SDK */ +/** + * A default FileIO factory implementation for creating Iceberg {@link FileIO} instances with + * contextual table-level properties. + * + * <p>This class acts as a translation layer between Polaris properties and the properties required + * by Iceberg's {@link FileIO}. For example, it evaluates storage actions and retrieves subscoped + * credentials to initialize a {@link FileIO} instance with the most limited permissions necessary. + */ @ApplicationScoped @Identifier("default") public class DefaultFileIOFactory implements FileIOFactory { + + private final RealmEntityManagerFactory realmEntityManagerFactory; + private final MetaStoreManagerFactory metaStoreManagerFactory; + private final PolarisConfigurationStore configurationStore; + + @Inject + public DefaultFileIOFactory( + RealmEntityManagerFactory realmEntityManagerFactory, + MetaStoreManagerFactory metaStoreManagerFactory, + PolarisConfigurationStore configurationStore) { + this.realmEntityManagerFactory = realmEntityManagerFactory; + this.metaStoreManagerFactory = metaStoreManagerFactory; + this.configurationStore = configurationStore; + } + + @Override + public FileIO loadFileIO( + @Nonnull RealmId realmId, + @Nonnull String ioImplClassName, + @Nonnull Map<String, String> properties) { + return loadFileIOInternal(ioImplClassName, properties); + } + @Override - public FileIO loadFileIO(String impl, Map<String, String> properties) { - return CatalogUtil.loadFileIO(impl, properties, new Configuration()); + public FileIO loadFileIO( + @Nonnull RealmId realmId, + @Nonnull String ioImplClassName, + @Nonnull Map<String, String> properties, + @Nonnull TableIdentifier identifier, + @Nonnull Set<String> tableLocations, + @Nonnull Set<PolarisStorageActions> storageActions, + @Nonnull PolarisResolvedPathWrapper resolvedEntityPath) { + PolarisEntityManager entityManager = + realmEntityManagerFactory.getOrCreateEntityManager(realmId); + PolarisCredentialVendor credentialVendor = + metaStoreManagerFactory.getOrCreateMetaStoreManager(realmId); + PolarisMetaStoreSession metaStoreSession = + metaStoreManagerFactory.getOrCreateSessionSupplier(realmId).get(); + + // Get subcoped creds + properties = new HashMap<>(properties); + Optional<PolarisEntity> storageInfoEntity = + FileIOUtil.findStorageInfoFromHierarchy(resolvedEntityPath); + Map<String, String> credentialsMap = + storageInfoEntity + .map( + storageInfo -> + FileIOUtil.refreshCredentials( + realmId, + entityManager, + credentialVendor, + metaStoreSession, + configurationStore, + identifier, + tableLocations, + storageActions, + storageInfo)) + .orElse(Map.of()); + + // Update the FileIO before we write the new metadata file Review Comment: I just copied this comment from `refreshIOWithCredentials`, will revise the comment. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@polaris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org