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 438d06cf7 test(integration): refactor 
PolarisRestCatalogIntegrationTest to run against any cloud provider (#1934)
438d06cf7 is described below

commit 438d06cf77169d56050948fe46a3763bb59e8c76
Author: Sushant Raikar <[email protected]>
AuthorDate: Fri Jun 27 14:18:13 2025 -0700

    test(integration): refactor PolarisRestCatalogIntegrationTest to run 
against any cloud provider (#1934)
    
    * Make Catalog Integration Test suite cloud native
---
 LICENSE                                            |  2 +-
 .../test/PolarisRestCatalogAwsIntegrationTest.java | 49 +++++++++++++
 .../PolarisRestCatalogAzureIntegrationTest.java    | 45 ++++++++++++
 .../PolarisRestCatalogFileIntegrationTest.java     | 59 ++++++++++++++++
 .../test/PolarisRestCatalogGcpIntegrationTest.java | 46 ++++++++++++
 ...java => PolarisRestCatalogIntegrationBase.java} | 82 +++++++++++-----------
 .../src/main/resources/META-INF/LICENSE            |  2 +-
 runtime/service/README-quarkus.md                  | 24 +++++++
 ...CatalogIT.java => QuarkusRestCatalogAwsIT.java} |  4 +-
 ...talogIT.java => QuarkusRestCatalogAzureIT.java} |  4 +-
 ...atalogIT.java => QuarkusRestCatalogFileIT.java} |  4 +-
 ...CatalogIT.java => QuarkusRestCatalogGcpIT.java} |  4 +-
 .../it/relational/jdbc/JdbcRestCatalogIT.java      |  4 +-
 ... => QuarkusRestCatalogFileIntegrationTest.java} |  6 +-
 .../QuarkusRestCatalogViewAwsIntegrationTest.java  | 52 --------------
 ...QuarkusRestCatalogViewAzureIntegrationTest.java | 51 --------------
 .../QuarkusRestCatalogViewGcpIntegrationTest.java  | 50 -------------
 17 files changed, 279 insertions(+), 209 deletions(-)

diff --git a/LICENSE b/LICENSE
index 93cc39a5c..4330ca154 100644
--- a/LICENSE
+++ b/LICENSE
@@ -217,7 +217,7 @@ This product includes code from Apache Iceberg.
 
 * spec/iceberg-rest-catalog-open-api.yaml
 * spec/polaris-catalog-apis/oauth-tokens-api.yaml
-* 
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java
+* 
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java
 * 
service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java
 * 
service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/CatalogHandlerUtils.java
 * 
plugins/spark/v3.5/spark/src/main/java/org/apache/polaris/spark/PolarisRESTCatalog.java
diff --git 
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogAwsIntegrationTest.java
 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogAwsIntegrationTest.java
new file mode 100644
index 000000000..11abab685
--- /dev/null
+++ 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogAwsIntegrationTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.service.it.test;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+import org.apache.polaris.core.admin.model.AwsStorageConfigInfo;
+import org.apache.polaris.core.admin.model.StorageConfigInfo;
+import org.assertj.core.util.Strings;
+
+/** Runs PolarisRestCatalogIntegrationBase test on AWS. */
+public class PolarisRestCatalogAwsIntegrationTest extends 
PolarisRestCatalogIntegrationBase {
+  public static final String ROLE_ARN =
+      Optional.ofNullable(System.getenv("INTEGRATION_TEST_ROLE_ARN"))
+          .or(() -> 
Optional.ofNullable(System.getenv("INTEGRATION_TEST_S3_ROLE_ARN")))
+          .orElse("arn:aws:iam::123456789012:role/my-role");
+  public static final String BASE_LOCATION = 
System.getenv("INTEGRATION_TEST_S3_PATH");
+
+  @Override
+  protected StorageConfigInfo getStorageConfigInfo() {
+    return AwsStorageConfigInfo.builder()
+        .setRoleArn(ROLE_ARN)
+        .setStorageType(StorageConfigInfo.StorageTypeEnum.S3)
+        .setAllowedLocations(List.of(BASE_LOCATION))
+        .build();
+  }
+
+  @Override
+  protected boolean shouldSkip() {
+    return Stream.of(BASE_LOCATION, ROLE_ARN).anyMatch(Strings::isNullOrEmpty);
+  }
+}
diff --git 
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogAzureIntegrationTest.java
 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogAzureIntegrationTest.java
new file mode 100644
index 000000000..8453b5617
--- /dev/null
+++ 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogAzureIntegrationTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.service.it.test;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polaris.core.admin.model.AzureStorageConfigInfo;
+import org.apache.polaris.core.admin.model.StorageConfigInfo;
+import org.assertj.core.util.Strings;
+
+/** Runs PolarisRestCatalogIntegrationBase test on Azure. */
+public class PolarisRestCatalogAzureIntegrationTest extends 
PolarisRestCatalogIntegrationBase {
+  public static final String TENANT_ID = 
System.getenv("INTEGRATION_TEST_AZURE_TENANT_ID");
+  public static final String BASE_LOCATION = 
System.getenv("INTEGRATION_TEST_AZURE_PATH");
+
+  @Override
+  protected StorageConfigInfo getStorageConfigInfo() {
+    return AzureStorageConfigInfo.builder()
+        .setTenantId(TENANT_ID)
+        .setStorageType(StorageConfigInfo.StorageTypeEnum.AZURE)
+        .setAllowedLocations(List.of(BASE_LOCATION))
+        .build();
+  }
+
+  @Override
+  protected boolean shouldSkip() {
+    return Stream.of(BASE_LOCATION, 
TENANT_ID).anyMatch(Strings::isNullOrEmpty);
+  }
+}
diff --git 
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogFileIntegrationTest.java
 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogFileIntegrationTest.java
new file mode 100644
index 000000000..3cd2face1
--- /dev/null
+++ 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogFileIntegrationTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.service.it.test;
+
+import java.net.URI;
+import java.nio.file.Path;
+import java.util.List;
+import org.apache.polaris.core.admin.model.FileStorageConfigInfo;
+import org.apache.polaris.core.admin.model.StorageConfigInfo;
+import org.apache.polaris.service.it.env.IntegrationTestsHelper;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.io.TempDir;
+
+/** Runs PolarisRestCatalogIntegrationBase test on the local filesystem. */
+public class PolarisRestCatalogFileIntegrationTest extends 
PolarisRestCatalogIntegrationBase {
+
+  public static String baseLocation;
+
+  @BeforeAll
+  static void setup(@TempDir Path tempDir) {
+    URI tempDirURI = IntegrationTestsHelper.getTemporaryDirectory(tempDir);
+    baseLocation = stripTrailingSlash(tempDirURI.toString());
+  }
+
+  @Override
+  protected StorageConfigInfo getStorageConfigInfo() {
+    return FileStorageConfigInfo.builder()
+        .setStorageType(StorageConfigInfo.StorageTypeEnum.FILE)
+        .setAllowedLocations(List.of(baseLocation, "file://"))
+        .build();
+  }
+
+  @Override
+  protected boolean shouldSkip() {
+    return false;
+  }
+
+  private static String stripTrailingSlash(String uri) {
+    return uri.endsWith("/") && uri.length() > "file:///".length()
+        ? uri.substring(0, uri.length() - 1)
+        : uri;
+  }
+}
diff --git 
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogGcpIntegrationTest.java
 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogGcpIntegrationTest.java
new file mode 100644
index 000000000..92dd96973
--- /dev/null
+++ 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogGcpIntegrationTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.service.it.test;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polaris.core.admin.model.GcpStorageConfigInfo;
+import org.apache.polaris.core.admin.model.StorageConfigInfo;
+import org.assertj.core.util.Strings;
+
+/** Runs PolarisRestCatalogIntegrationBase test on GCP. */
+public class PolarisRestCatalogGcpIntegrationTest extends 
PolarisRestCatalogIntegrationBase {
+  public static final String SERVICE_ACCOUNT =
+      System.getenv("INTEGRATION_TEST_GCS_SERVICE_ACCOUNT");
+  public static final String BASE_LOCATION = 
System.getenv("INTEGRATION_TEST_GCS_PATH");
+
+  @Override
+  protected StorageConfigInfo getStorageConfigInfo() {
+    return GcpStorageConfigInfo.builder()
+        .setGcsServiceAccount(SERVICE_ACCOUNT)
+        .setStorageType(StorageConfigInfo.StorageTypeEnum.GCS)
+        .setAllowedLocations(List.of(BASE_LOCATION))
+        .build();
+  }
+
+  @Override
+  protected boolean shouldSkip() {
+    return Stream.of(BASE_LOCATION, 
SERVICE_ACCOUNT).anyMatch(Strings::isNullOrEmpty);
+  }
+}
diff --git 
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java
 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java
similarity index 96%
rename from 
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java
rename to 
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java
index a999ab9fe..cd62cb1ff 100644
--- 
a/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java
+++ 
b/integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java
@@ -35,7 +35,6 @@ import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.Method;
 import java.net.URI;
-import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -68,12 +67,10 @@ import org.apache.iceberg.rest.RESTUtil;
 import org.apache.iceberg.rest.requests.CreateTableRequest;
 import org.apache.iceberg.rest.responses.ErrorResponse;
 import org.apache.iceberg.types.Types;
-import org.apache.polaris.core.admin.model.AwsStorageConfigInfo;
 import org.apache.polaris.core.admin.model.Catalog;
 import org.apache.polaris.core.admin.model.CatalogGrant;
 import org.apache.polaris.core.admin.model.CatalogPrivilege;
 import org.apache.polaris.core.admin.model.CatalogProperties;
-import org.apache.polaris.core.admin.model.FileStorageConfigInfo;
 import org.apache.polaris.core.admin.model.GrantResource;
 import org.apache.polaris.core.admin.model.GrantResources;
 import org.apache.polaris.core.admin.model.NamespaceGrant;
@@ -92,7 +89,6 @@ import org.apache.polaris.service.it.env.CatalogApi;
 import org.apache.polaris.service.it.env.ClientCredentials;
 import org.apache.polaris.service.it.env.GenericTableApi;
 import org.apache.polaris.service.it.env.IcebergHelper;
-import org.apache.polaris.service.it.env.IntegrationTestsHelper;
 import org.apache.polaris.service.it.env.ManagementApi;
 import org.apache.polaris.service.it.env.PolarisApiEndpoints;
 import org.apache.polaris.service.it.env.PolarisClient;
@@ -110,7 +106,6 @@ import org.junit.jupiter.api.BeforeEach;
 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
@@ -124,15 +119,15 @@ import org.junit.jupiter.api.io.TempDir;
  *     CODE_COPIED_TO_POLARIS From Apache Iceberg Version: 1.7.1
  */
 @ExtendWith(PolarisIntegrationTestExtension.class)
-public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog> {
-  private static final String TEST_ROLE_ARN =
-      Optional.ofNullable(System.getenv("INTEGRATION_TEST_ROLE_ARN"))
-          .orElse("arn:aws:iam::123456789012:role/my-role");
-
-  private static URI s3BucketBase;
-  private static URI externalCatalogBase;
-
+public abstract class PolarisRestCatalogIntegrationBase extends 
CatalogTests<RESTCatalog> {
   protected static final String VIEW_QUERY = "select * from ns1.layer1_table";
+  // subpath shouldn't start with a slash, as it is appended to the base URI
+  private static final String CATALOG_LOCATION_SUBPATH =
+      
Optional.ofNullable(System.getenv("INTEGRATION_TEST_CATALOG_LOCATION_SUBPATH"))
+          .orElse("path/to/data");
+  private static final String EXTERNAL_CATALOG_LOCATION_SUBPATH =
+      
Optional.ofNullable(System.getenv("INTEGRATION_TEST_EXTERNAL_CATALOG_LOCATION_SUBPATH"))
+          .orElse("external-catalog");
   private static ClientCredentials adminCredentials;
   private static PolarisApiEndpoints endpoints;
   private static PolarisClient client;
@@ -144,9 +139,8 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
   private RESTCatalog restCatalog;
   private String currentCatalogName;
   private Map<String, String> restCatalogConfig;
-
-  private final String catalogBaseLocation =
-      s3BucketBase + "/" + System.getenv("USER") + "/path/to/data";
+  private URI externalCatalogBase;
+  private String catalogBaseLocation;
 
   private static final Map<String, String> DEFAULT_REST_CATALOG_CONFIG =
       Map.of(
@@ -181,16 +175,26 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
     String[] value() default {};
   }
 
+  /**
+   * Get the storage configuration information for the catalog.
+   *
+   * @return StorageConfigInfo instance containing the storage configuration
+   */
+  protected abstract StorageConfigInfo getStorageConfigInfo();
+
+  /**
+   * Determine whether the test should be skipped based on the environment or 
configuration.
+   *
+   * @return true if the test should be skipped, false otherwise
+   */
+  protected abstract boolean shouldSkip();
+
   @BeforeAll
-  static void setup(
-      PolarisApiEndpoints apiEndpoints, ClientCredentials credentials, 
@TempDir Path tempDir) {
+  static void setup(PolarisApiEndpoints apiEndpoints, ClientCredentials 
credentials) {
     adminCredentials = credentials;
     endpoints = apiEndpoints;
     client = polarisClient(endpoints);
     managementApi = client.managementApi(credentials);
-    URI testRootUri = IntegrationTestsHelper.getTemporaryDirectory(tempDir);
-    s3BucketBase = testRootUri.resolve("my-bucket");
-    externalCatalogBase = testRootUri.resolve("external-catalog");
   }
 
   static {
@@ -204,6 +208,7 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
 
   @BeforeEach
   public void before(TestInfo testInfo) {
+    Assumptions.assumeThat(shouldSkip()).isFalse();
     String principalName = client.newEntityName("snowman-rest");
     String principalRoleName = client.newEntityName("rest-admin");
     principalCredentials = 
managementApi.createPrincipalWithRole(principalName, principalRoleName);
@@ -213,14 +218,13 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
 
     Method method = testInfo.getTestMethod().orElseThrow();
     currentCatalogName = client.newEntityName(method.getName());
-    AwsStorageConfigInfo awsConfigModel =
-        AwsStorageConfigInfo.builder()
-            .setRoleArn(TEST_ROLE_ARN)
-            .setExternalId("externalId")
-            .setUserArn("a:user:arn")
-            .setStorageType(StorageConfigInfo.StorageTypeEnum.S3)
-            .setAllowedLocations(List.of("s3://my-old-bucket/path/to/data"))
-            .build();
+    StorageConfigInfo storageConfig = getStorageConfigInfo();
+    URI testRuntimeURI = 
URI.create(storageConfig.getAllowedLocations().getFirst());
+    catalogBaseLocation = testRuntimeURI + "/" + CATALOG_LOCATION_SUBPATH;
+    externalCatalogBase =
+        URI.create(
+            testRuntimeURI + "/" + EXTERNAL_CATALOG_LOCATION_SUBPATH + "/" + 
method.getName());
+
     Optional<CatalogConfig> catalogConfig =
         Optional.ofNullable(method.getAnnotation(CatalogConfig.class));
 
@@ -232,7 +236,7 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
     }
     catalogPropsBuilder.addProperty(
         FeatureConfiguration.DROP_WITH_PURGE_ENABLED.catalogConfig(), "true");
-    if (!s3BucketBase.getScheme().equals("file")) {
+    if (!testRuntimeURI.getScheme().equals("file")) {
       catalogPropsBuilder.addProperty(
           CatalogEntity.REPLACE_NEW_LOCATION_PREFIX_WITH_CATALOG_DEFAULT_KEY, 
"file:");
     }
@@ -241,11 +245,7 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
             
.setType(catalogConfig.map(CatalogConfig::value).orElse(Catalog.TypeEnum.INTERNAL))
             .setName(currentCatalogName)
             .setProperties(catalogPropsBuilder.build())
-            .setStorageConfigInfo(
-                s3BucketBase.getScheme().equals("file")
-                    ? new FileStorageConfigInfo(
-                        StorageConfigInfo.StorageTypeEnum.FILE, 
List.of("file://"))
-                    : awsConfigModel)
+            .setStorageConfigInfo(storageConfig)
             .build();
 
     managementApi.createCatalog(principalRoleName, catalog);
@@ -701,12 +701,12 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
         TableMetadata.newTableMetadata(
             new Schema(List.of(Types.NestedField.required(1, "col1", new 
Types.StringType()))),
             PartitionSpec.unpartitioned(),
-            "file:///tmp/ns1/my_table",
+            externalCatalogBase + "/ns1/my_table",
             Map.of());
     try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
       resolvingFileIO.initialize(Map.of());
       resolvingFileIO.setConf(new Configuration());
-      String fileLocation = 
"file:///tmp/ns1/my_table/metadata/v1.metadata.json";
+      String fileLocation = externalCatalogBase + 
"/ns1/my_table/metadata/v1.metadata.json";
       TableMetadataParser.write(tableMetadata, 
resolvingFileIO.newOutputFile(fileLocation));
       restCatalog.registerTable(TableIdentifier.of(ns1, "my_table_etagged"), 
fileLocation);
       Invocation invocation =
@@ -745,12 +745,12 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
         TableMetadata.newTableMetadata(
             new Schema(List.of(Types.NestedField.required(1, "col1", new 
Types.StringType()))),
             PartitionSpec.unpartitioned(),
-            "file:///tmp/ns1/my_table",
+            externalCatalogBase + "/ns1/my_table",
             Map.of());
     try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
       resolvingFileIO.initialize(Map.of());
       resolvingFileIO.setConf(new Configuration());
-      String fileLocation = 
"file:///tmp/ns1/my_table/metadata/v1.metadata.json";
+      String fileLocation = externalCatalogBase + 
"/ns1/my_table/metadata/v1.metadata.json";
       TableMetadataParser.write(tableMetadata, 
resolvingFileIO.newOutputFile(fileLocation));
 
       Invocation registerInvocation =
@@ -788,12 +788,12 @@ public class PolarisRestCatalogIntegrationTest extends 
CatalogTests<RESTCatalog>
         TableMetadata.newTableMetadata(
             new Schema(List.of(Types.NestedField.required(1, "col1", new 
Types.StringType()))),
             PartitionSpec.unpartitioned(),
-            "file:///tmp/ns1/my_table",
+            externalCatalogBase + "/ns1/my_table",
             Map.of());
     try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
       resolvingFileIO.initialize(Map.of());
       resolvingFileIO.setConf(new Configuration());
-      String fileLocation = 
"file:///tmp/ns1/my_table/metadata/v1.metadata.json";
+      String fileLocation = externalCatalogBase + 
"/ns1/my_table/metadata/v1.metadata.json";
       TableMetadataParser.write(tableMetadata, 
resolvingFileIO.newOutputFile(fileLocation));
 
       Invocation createInvocation =
diff --git a/integration-tests/src/main/resources/META-INF/LICENSE 
b/integration-tests/src/main/resources/META-INF/LICENSE
index be81989a6..30ac2d34f 100644
--- a/integration-tests/src/main/resources/META-INF/LICENSE
+++ b/integration-tests/src/main/resources/META-INF/LICENSE
@@ -204,7 +204,7 @@
 
 This product includes code from Apache Iceberg.
 
-* 
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationTest.java
+* 
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java
 
 Copyright: Copyright 2017-2025 The Apache Software Foundation
 Home page: https://iceberg.apache.org
diff --git a/runtime/service/README-quarkus.md 
b/runtime/service/README-quarkus.md
index cf303aa10..0a42c319d 100644
--- a/runtime/service/README-quarkus.md
+++ b/runtime/service/README-quarkus.md
@@ -79,6 +79,30 @@ configuration property).
 
 You can find more details here: https://quarkus.io/guides/config
 
+# Integration tests
+Integration tests from the :polaris-tests module can be run against a local 
Polaris Quarkus instance
+for each supported cloud storage. Set the appropriate environment variables 
for your target cloud,
+then run the tests as shown below.
+
+For S3:
+```shell
+export INTEGRATION_TEST_S3_PATH="s3://bucket/subpath"
+export INTEGRATION_TEST_S3_ROLE_ARN="your-role-arn"
+./gradlew :polaris-runtime-service:intTest
+```
+For Azure:
+```shell
+export INTEGRATION_TEST_AZURE_PATH="abfss://bucket/subpath"
+export INTEGRATION_TEST_AZURE_TENANT_ID="your-tenant-id"
+./gradlew :polaris-runtime-service:intTest
+``` 
+For GCS:
+```shell
+export INTEGRATION_TEST_GCS_PATH="gs://bucket/subpath"
+export INTEGRATION_TEST_GCS_SERVICE_ACCOUNT="your-service-account"
+./gradlew :polaris-runtime-service:intTest
+```
+
 # TODO
 
 * Modify `CallContext` and remove all usages of `ThreadLocal`, replace with 
proper context propagation.
diff --git 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogAwsIT.java
similarity index 84%
copy from 
runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
copy to 
runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogAwsIT.java
index 5d214d188..b0b423ad3 100644
--- 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
+++ 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogAwsIT.java
@@ -19,7 +19,7 @@
 package org.apache.polaris.service.quarkus.it;
 
 import io.quarkus.test.junit.QuarkusIntegrationTest;
-import org.apache.polaris.service.it.test.PolarisRestCatalogIntegrationTest;
+import org.apache.polaris.service.it.test.PolarisRestCatalogAwsIntegrationTest;
 
 @QuarkusIntegrationTest
-public class QuarkusRestCatalogIT extends PolarisRestCatalogIntegrationTest {}
+public class QuarkusRestCatalogAwsIT extends 
PolarisRestCatalogAwsIntegrationTest {}
diff --git 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogAzureIT.java
similarity index 84%
copy from 
runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
copy to 
runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogAzureIT.java
index 5d214d188..6a829122d 100644
--- 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
+++ 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogAzureIT.java
@@ -19,7 +19,7 @@
 package org.apache.polaris.service.quarkus.it;
 
 import io.quarkus.test.junit.QuarkusIntegrationTest;
-import org.apache.polaris.service.it.test.PolarisRestCatalogIntegrationTest;
+import 
org.apache.polaris.service.it.test.PolarisRestCatalogAzureIntegrationTest;
 
 @QuarkusIntegrationTest
-public class QuarkusRestCatalogIT extends PolarisRestCatalogIntegrationTest {}
+public class QuarkusRestCatalogAzureIT extends 
PolarisRestCatalogAzureIntegrationTest {}
diff --git 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogFileIT.java
similarity index 84%
copy from 
runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
copy to 
runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogFileIT.java
index 5d214d188..cd1905a0a 100644
--- 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
+++ 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogFileIT.java
@@ -19,7 +19,7 @@
 package org.apache.polaris.service.quarkus.it;
 
 import io.quarkus.test.junit.QuarkusIntegrationTest;
-import org.apache.polaris.service.it.test.PolarisRestCatalogIntegrationTest;
+import 
org.apache.polaris.service.it.test.PolarisRestCatalogFileIntegrationTest;
 
 @QuarkusIntegrationTest
-public class QuarkusRestCatalogIT extends PolarisRestCatalogIntegrationTest {}
+public class QuarkusRestCatalogFileIT extends 
PolarisRestCatalogFileIntegrationTest {}
diff --git 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogGcpIT.java
similarity index 84%
rename from 
runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
rename to 
runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogGcpIT.java
index 5d214d188..ceccad902 100644
--- 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIT.java
+++ 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogGcpIT.java
@@ -19,7 +19,7 @@
 package org.apache.polaris.service.quarkus.it;
 
 import io.quarkus.test.junit.QuarkusIntegrationTest;
-import org.apache.polaris.service.it.test.PolarisRestCatalogIntegrationTest;
+import org.apache.polaris.service.it.test.PolarisRestCatalogGcpIntegrationTest;
 
 @QuarkusIntegrationTest
-public class QuarkusRestCatalogIT extends PolarisRestCatalogIntegrationTest {}
+public class QuarkusRestCatalogGcpIT extends 
PolarisRestCatalogGcpIntegrationTest {}
diff --git 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java
 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java
index 59b35fe91..c7192437f 100644
--- 
a/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java
+++ 
b/runtime/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java
@@ -20,9 +20,9 @@ package org.apache.polaris.service.quarkus.it.relational.jdbc;
 
 import io.quarkus.test.junit.QuarkusIntegrationTest;
 import io.quarkus.test.junit.TestProfile;
-import org.apache.polaris.service.it.test.PolarisRestCatalogIntegrationTest;
+import 
org.apache.polaris.service.it.test.PolarisRestCatalogFileIntegrationTest;
 import org.apache.polaris.test.commons.RelationalJdbcProfile;
 
 @TestProfile(RelationalJdbcProfile.class)
 @QuarkusIntegrationTest
-public class JdbcRestCatalogIT extends PolarisRestCatalogIntegrationTest {}
+public class JdbcRestCatalogIT extends PolarisRestCatalogFileIntegrationTest {}
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIntegrationTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogFileIntegrationTest.java
similarity index 86%
rename from 
runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIntegrationTest.java
rename to 
runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogFileIntegrationTest.java
index b2ddd79b0..126ab23f8 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogIntegrationTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogFileIntegrationTest.java
@@ -22,11 +22,11 @@ import io.quarkus.test.junit.QuarkusTest;
 import io.quarkus.test.junit.QuarkusTestProfile;
 import io.quarkus.test.junit.TestProfile;
 import java.util.Map;
-import org.apache.polaris.service.it.test.PolarisRestCatalogIntegrationTest;
+import 
org.apache.polaris.service.it.test.PolarisRestCatalogFileIntegrationTest;
 
 @QuarkusTest
-@TestProfile(QuarkusRestCatalogIntegrationTest.Profile.class)
-public class QuarkusRestCatalogIntegrationTest extends 
PolarisRestCatalogIntegrationTest {
+@TestProfile(QuarkusRestCatalogFileIntegrationTest.Profile.class)
+public class QuarkusRestCatalogFileIntegrationTest extends 
PolarisRestCatalogFileIntegrationTest {
 
   public static class Profile implements QuarkusTestProfile {
 
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewAwsIntegrationTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewAwsIntegrationTest.java
deleted file mode 100644
index 16380c24d..000000000
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewAwsIntegrationTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.service.quarkus.it;
-
-import io.quarkus.test.junit.QuarkusTest;
-import io.quarkus.test.junit.QuarkusTestProfile;
-import io.quarkus.test.junit.TestProfile;
-import java.lang.reflect.Field;
-import java.nio.file.Path;
-import java.util.Map;
-import org.apache.iceberg.view.ViewCatalogTests;
-import 
org.apache.polaris.service.it.test.PolarisRestCatalogViewAwsIntegrationTest;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.io.TempDir;
-
-@QuarkusTest
-@TestProfile(QuarkusRestCatalogViewAwsIntegrationTest.Profile.class)
-public class QuarkusRestCatalogViewAwsIntegrationTest
-    extends PolarisRestCatalogViewAwsIntegrationTest {
-
-  public static class Profile implements QuarkusTestProfile {
-
-    @Override
-    public Map<String, String> getConfigOverrides() {
-      return Map.of("polaris.features.\"SUPPORTED_CATALOG_STORAGE_TYPES\"", 
"[\"S3\"]");
-    }
-  }
-
-  @BeforeEach
-  public void setUpTempDir(@TempDir Path tempDir) throws Exception {
-    // see https://github.com/quarkusio/quarkus/issues/13261
-    Field field = ViewCatalogTests.class.getDeclaredField("tempDir");
-    field.setAccessible(true);
-    field.set(this, tempDir);
-  }
-}
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewAzureIntegrationTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewAzureIntegrationTest.java
deleted file mode 100644
index 49ff842b7..000000000
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewAzureIntegrationTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.service.quarkus.it;
-
-import io.quarkus.test.junit.QuarkusTest;
-import io.quarkus.test.junit.QuarkusTestProfile;
-import io.quarkus.test.junit.TestProfile;
-import java.lang.reflect.Field;
-import java.nio.file.Path;
-import java.util.Map;
-import org.apache.iceberg.view.ViewCatalogTests;
-import 
org.apache.polaris.service.it.test.PolarisRestCatalogViewAzureIntegrationTest;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.io.TempDir;
-
-@QuarkusTest
-@TestProfile(QuarkusRestCatalogViewAzureIntegrationTest.Profile.class)
-public class QuarkusRestCatalogViewAzureIntegrationTest
-    extends PolarisRestCatalogViewAzureIntegrationTest {
-  public static class Profile implements QuarkusTestProfile {
-
-    @Override
-    public Map<String, String> getConfigOverrides() {
-      return Map.of("polaris.features.\"SUPPORTED_CATALOG_STORAGE_TYPES\"", 
"[\"AZURE\"]");
-    }
-  }
-
-  @BeforeEach
-  public void setUpTempDir(@TempDir Path tempDir) throws Exception {
-    // see https://github.com/quarkusio/quarkus/issues/13261
-    Field field = ViewCatalogTests.class.getDeclaredField("tempDir");
-    field.setAccessible(true);
-    field.set(this, tempDir);
-  }
-}
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewGcpIntegrationTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewGcpIntegrationTest.java
deleted file mode 100644
index ef04d745e..000000000
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/it/QuarkusRestCatalogViewGcpIntegrationTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.service.quarkus.it;
-
-import io.quarkus.test.junit.QuarkusTest;
-import io.quarkus.test.junit.QuarkusTestProfile;
-import java.lang.reflect.Field;
-import java.nio.file.Path;
-import java.util.Map;
-import org.apache.iceberg.view.ViewCatalogTests;
-import 
org.apache.polaris.service.it.test.PolarisRestCatalogViewGcpIntegrationTest;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.io.TempDir;
-
-@QuarkusTest
-public class QuarkusRestCatalogViewGcpIntegrationTest
-    extends PolarisRestCatalogViewGcpIntegrationTest {
-
-  public static class Profile implements QuarkusTestProfile {
-
-    @Override
-    public Map<String, String> getConfigOverrides() {
-      return Map.of("polaris.features.\"SUPPORTED_CATALOG_STORAGE_TYPES\"", 
"[\"GCS\"]");
-    }
-  }
-
-  @BeforeEach
-  public void setUpTempDir(@TempDir Path tempDir) throws Exception {
-    // see https://github.com/quarkusio/quarkus/issues/13261
-    Field field = ViewCatalogTests.class.getDeclaredField("tempDir");
-    field.setAccessible(true);
-    field.set(this, tempDir);
-  }
-}


Reply via email to