This is an automated email from the ASF dual-hosted git repository.
dimas 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 f158f2e6c Unblock test `createViewWithCustomMetadataLocation` (#1320)
f158f2e6c is described below
commit f158f2e6cea6c967c7b6999844e38ccd4cf0e34b
Author: Liam Bao <[email protected]>
AuthorDate: Mon Jun 2 13:26:29 2025 -0400
Unblock test `createViewWithCustomMetadataLocation` (#1320)
* Add test for invalid custom metadata location
* Add missing properties during table/view creation
---
.../PolarisRestCatalogViewIntegrationBase.java | 91 ++++++++++++++++++++--
.../storage/PolarisStorageConfigurationInfo.java | 1 +
2 files changed, 84 insertions(+), 8 deletions(-)
diff --git
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogViewIntegrationBase.java
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogViewIntegrationBase.java
index eda721b32..25fac69ac 100644
---
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogViewIntegrationBase.java
+++
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogViewIntegrationBase.java
@@ -20,9 +20,16 @@ package org.apache.polaris.service.it.test;
import static org.apache.polaris.service.it.env.PolarisClient.polarisClient;
+import com.google.common.collect.ImmutableMap;
import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Map;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.exceptions.ForbiddenException;
import org.apache.iceberg.rest.RESTCatalog;
+import org.apache.iceberg.view.BaseView;
+import org.apache.iceberg.view.View;
import org.apache.iceberg.view.ViewCatalogTests;
import org.apache.polaris.core.admin.model.Catalog;
import org.apache.polaris.core.admin.model.CatalogProperties;
@@ -31,22 +38,24 @@ import
org.apache.polaris.core.admin.model.PrincipalWithCredentials;
import org.apache.polaris.core.admin.model.StorageConfigInfo;
import org.apache.polaris.core.config.FeatureConfiguration;
import org.apache.polaris.core.entity.CatalogEntity;
+import org.apache.polaris.core.entity.table.IcebergTableLikeEntity;
import org.apache.polaris.service.it.env.ClientCredentials;
import org.apache.polaris.service.it.env.IcebergHelper;
import org.apache.polaris.service.it.env.ManagementApi;
import org.apache.polaris.service.it.env.PolarisApiEndpoints;
import org.apache.polaris.service.it.env.PolarisClient;
import org.apache.polaris.service.it.ext.PolarisIntegrationTestExtension;
+import org.assertj.core.api.Assertions;
import org.assertj.core.api.Assumptions;
import org.assertj.core.configuration.PreferredAssumptionException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
/**
* Import the full core Iceberg catalog tests by hitting the REST service via
the RESTCatalog
@@ -175,15 +184,81 @@ public abstract class
PolarisRestCatalogViewIntegrationBase extends ViewCatalogT
return true;
}
- /** TODO: Unblock this test, see:
https://github.com/apache/polaris/issues/1273 */
@Override
@Test
- @Disabled(
- """
- Disabled because the behavior is not applicable to Polaris.
- To unblock, update this to expect an exception and add a
Polaris-specific test.
- """)
public void createViewWithCustomMetadataLocation() {
- super.createViewWithCustomMetadataLocation();
+ Assertions.assertThatThrownBy(super::createViewWithCustomMetadataLocation)
+ .isInstanceOf(ForbiddenException.class)
+ .hasMessageContaining("Forbidden: Invalid locations");
+ }
+
+ @Test
+ public void createViewWithCustomMetadataLocationUsingPolaris(@TempDir Path
tempDir) {
+ TableIdentifier identifier = TableIdentifier.of("ns", "view");
+
+ String location = Paths.get(tempDir.toUri().toString()).toString();
+ String customLocation = Paths.get(tempDir.toUri().toString(),
"custom-location").toString();
+ String customLocation2 = Paths.get(tempDir.toUri().toString(),
"custom-location2").toString();
+ String customLocationChild =
+ Paths.get(tempDir.toUri().toString(),
"custom-location/child").toString();
+
+ catalog()
+ .createNamespace(
+ identifier.namespace(),
+ ImmutableMap.of(
+
IcebergTableLikeEntity.USER_SPECIFIED_WRITE_METADATA_LOCATION_KEY, location));
+
+ Assertions.assertThat(catalog().viewExists(identifier)).as("View should
not exist").isFalse();
+
+ // CAN create a view with a custom metadata location
`baseLocation/customLocation`,
+ // as long as the location is within the parent namespace's
`write.metadata.path=baseLocation`
+ View view =
+ catalog()
+ .buildView(identifier)
+ .withSchema(SCHEMA)
+ .withDefaultNamespace(identifier.namespace())
+ .withDefaultCatalog(catalog().name())
+ .withQuery("spark", "select * from ns.tbl")
+ .withProperty(
+
IcebergTableLikeEntity.USER_SPECIFIED_WRITE_METADATA_LOCATION_KEY,
customLocation)
+ .withLocation(location)
+ .create();
+
+ Assertions.assertThat(view).isNotNull();
+ Assertions.assertThat(catalog().viewExists(identifier)).as("View should
exist").isTrue();
+
Assertions.assertThat(view.properties()).containsEntry("write.metadata.path",
customLocation);
+ Assertions.assertThat(((BaseView)
view).operations().current().metadataFileLocation())
+ .isNotNull()
+ .startsWith(customLocation);
+
+ // CANNOT update the view with a new metadata location
`baseLocation/customLocation2`,
+ // even though the new location is still under the parent namespace's
+ // `write.metadata.path=baseLocation`.
+ Assertions.assertThatThrownBy(
+ () ->
+ catalog()
+ .loadView(identifier)
+ .updateProperties()
+ .set(
+
IcebergTableLikeEntity.USER_SPECIFIED_WRITE_METADATA_LOCATION_KEY,
+ customLocation2)
+ .commit())
+ .isInstanceOf(ForbiddenException.class)
+ .hasMessageContaining("Forbidden: Invalid locations");
+
+ // CANNOT update the view with a child metadata location
`baseLocation/customLocation/child`,
+ // even though it is a subpath of the original view's
+ // `write.metadata.path=baseLocation/customLocation`.
+ Assertions.assertThatThrownBy(
+ () ->
+ catalog()
+ .loadView(identifier)
+ .updateProperties()
+ .set(
+
IcebergTableLikeEntity.USER_SPECIFIED_WRITE_METADATA_LOCATION_KEY,
+ customLocationChild)
+ .commit())
+ .isInstanceOf(ForbiddenException.class)
+ .hasMessageContaining("Forbidden: Invalid locations");
}
}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisStorageConfigurationInfo.java
b/polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisStorageConfigurationInfo.java
index e1ec45bdb..852e60b14 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisStorageConfigurationInfo.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisStorageConfigurationInfo.java
@@ -181,6 +181,7 @@ public abstract class PolarisStorageConfigurationInfo {
"Allowing unstructured table location for entity: {}",
entityPathReversed.get(0).getName());
+ // TODO: figure out the purpose of adding
`userSpecifiedWriteLocations`
List<String> locs =
userSpecifiedWriteLocations(entityPathReversed.get(0).getPropertiesAsMap());
return new StorageConfigurationOverride(