You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by pv...@apache.org on 2026/08/29 05:13:13 UTC

(iceberg) 02/02: Flink: Forward-port REST catalog support in CatalogTestBase to 2.2

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

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

commit 7858e8003eddda8af74e578f042b993fd32de6fc
Author: Talat Uyarer <ta...@apache.org>
AuthorDate: Fri Aug 28 12:09:42 2026 -0700

    Flink: Forward-port REST catalog support in CatalogTestBase to 2.2
---
 flink/v2.2/build.gradle                            |  1 +
 .../org/apache/iceberg/flink/CatalogTestBase.java  | 48 +++++++++++++++--
 .../flink/TestFlinkRESTCatalogDatabase.java        | 60 ++++++++++++++++++++++
 3 files changed, 104 insertions(+), 5 deletions(-)

diff --git a/flink/v2.2/build.gradle b/flink/v2.2/build.gradle
index b57d9383cf..ffd2f5dc2f 100644
--- a/flink/v2.2/build.gradle
+++ b/flink/v2.2/build.gradle
@@ -87,6 +87,7 @@ project(":iceberg-flink:iceberg-flink-${flinkMajorVersion}") {
     testImplementation project(path: ':iceberg-data', configuration: 'testArtifacts')
     testImplementation project(path: ':iceberg-orc', configuration: 'testArtifacts')
     testImplementation(testFixtures(project(':iceberg-parquet')))
+    testImplementation (project(path: ':iceberg-open-api', configuration: 'testFixturesRuntimeElements'))
 
     // By default, hive-exec is a fat/uber jar and it exports a guava library
     // that's really old. We use the core classifier to be able to override our guava
diff --git a/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/CatalogTestBase.java b/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/CatalogTestBase.java
index bd34e62817..36abcf6a4c 100644
--- a/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/CatalogTestBase.java
+++ b/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/CatalogTestBase.java
@@ -33,11 +33,17 @@ import org.apache.iceberg.catalog.Namespace;
 import org.apache.iceberg.catalog.SupportsNamespaces;
 import org.apache.iceberg.hadoop.HadoopCatalog;
 import org.apache.iceberg.relocated.com.google.common.base.Joiner;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
 import org.apache.iceberg.relocated.com.google.common.collect.Lists;
 import org.apache.iceberg.relocated.com.google.common.collect.Maps;
+import org.apache.iceberg.rest.RESTCatalog;
+import org.apache.iceberg.rest.RESTCatalogServer;
+import org.apache.iceberg.rest.RESTServerExtension;
 import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.junit.jupiter.api.io.TempDir;
 
 @ExtendWith(ParameterizedTestExtension.class)
@@ -46,7 +52,8 @@ public abstract class CatalogTestBase extends TestBase {
   /** Catalog implementations that SQL test suites can run against. */
   public enum CatalogType {
     HIVE("testhive"),
-    HADOOP("testhadoop");
+    HADOOP("testhadoop"),
+    REST("testrest");
 
     private final String catalogNamePrefix;
 
@@ -65,6 +72,21 @@ public abstract class CatalogTestBase extends TestBase {
   @TempDir protected File hiveWarehouse;
   @TempDir protected File hadoopWarehouse;
 
+  @RegisterExtension
+  private static final RESTServerExtension REST_SERVER_EXTENSION =
+      new RESTServerExtension(
+          ImmutableMap.of(
+              RESTCatalogServer.REST_PORT,
+              RESTServerExtension.FREE_PORT,
+              // In-memory sqlite database by default is private to the connection that created
+              // it. If more than 1 jdbc connection backs the catalog, the connections can see
+              // different database states, so limit the backend JdbcCatalog to a single
+              // connection.
+              CatalogProperties.CLIENT_POOL_SIZE,
+              "1"));
+
+  protected static RESTCatalog restCatalog;
+
   @Parameter(index = 0)
   protected CatalogType catalogType;
 
@@ -79,6 +101,7 @@ public abstract class CatalogTestBase extends TestBase {
   protected String flinkDatabase;
   protected Namespace icebergNamespace;
   protected boolean isHadoopCatalog;
+  protected boolean isRestCatalog;
 
   @Parameters(name = "catalogType={0}, baseNamespace={1}")
   protected static List<Object[]> parameters() {
@@ -88,14 +111,23 @@ public abstract class CatalogTestBase extends TestBase {
         new Object[] {CatalogType.HADOOP, Namespace.of("l0", "l1")});
   }
 
+  @BeforeAll
+  public static void initRestCatalog() {
+    restCatalog = REST_SERVER_EXTENSION.client();
+  }
+
   @BeforeEach
   public void before() {
     this.catalogName = catalogType.catalogName(baseNamespace);
     this.isHadoopCatalog = catalogType == CatalogType.HADOOP;
-    this.validationCatalog =
-        isHadoopCatalog
-            ? new HadoopCatalog(hiveConf, "file:" + hadoopWarehouse.getPath())
-            : catalog;
+    this.isRestCatalog = catalogType == CatalogType.REST;
+    if (isHadoopCatalog) {
+      this.validationCatalog = new HadoopCatalog(hiveConf, "file:" + hadoopWarehouse.getPath());
+    } else if (isRestCatalog) {
+      this.validationCatalog = restCatalog;
+    } else {
+      this.validationCatalog = catalog;
+    }
     this.validationNamespaceCatalog = (SupportsNamespaces) validationCatalog;
 
     config.put("type", "iceberg");
@@ -104,6 +136,12 @@ public abstract class CatalogTestBase extends TestBase {
     }
     if (isHadoopCatalog) {
       config.put(FlinkCatalogFactory.ICEBERG_CATALOG_TYPE, "hadoop");
+    } else if (isRestCatalog) {
+      config.put(FlinkCatalogFactory.ICEBERG_CATALOG_TYPE, "rest");
+      config.put(CatalogProperties.URI, restCatalog.properties().get(CatalogProperties.URI));
+      // disable Flink-side catalog caching so validations that write directly through
+      // restCatalog observe fresh metadata
+      config.put(CatalogProperties.CACHE_ENABLED, "false");
     } else {
       config.put(FlinkCatalogFactory.ICEBERG_CATALOG_TYPE, "hive");
       config.put(CatalogProperties.URI, getURI(hiveConf));
diff --git a/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/TestFlinkRESTCatalogDatabase.java b/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/TestFlinkRESTCatalogDatabase.java
new file mode 100644
index 0000000000..988e179fdf
--- /dev/null
+++ b/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/TestFlinkRESTCatalogDatabase.java
@@ -0,0 +1,60 @@
+/*
+ * 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.iceberg.flink;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.apache.iceberg.Parameters;
+import org.apache.iceberg.catalog.Namespace;
+import org.junit.jupiter.api.TestTemplate;
+
+/**
+ * Runs the {@link TestFlinkCatalogDatabase} suite against a REST catalog server backed by an
+ * in-memory JDBC catalog.
+ */
+public class TestFlinkRESTCatalogDatabase extends TestFlinkCatalogDatabase {
+
+  @Parameters(name = "catalogType={0}, baseNamespace={1}")
+  protected static List<Object[]> parameters() {
+    return Collections.singletonList(new Object[] {CatalogType.REST, Namespace.empty()});
+  }
+
+  @TestTemplate
+  @Override
+  public void testCreateNamespaceWithLocation() throws Exception {
+    // The JDBC-backed REST catalog stores the 'location' property verbatim instead of
+    // resolving it to a "file:" URI the way the Hive catalog does
+    assertThat(validationNamespaceCatalog.namespaceExists(icebergNamespace))
+        .as("Namespace should not already exist")
+        .isFalse();
+
+    Path location = temporaryDirectory;
+    sql("CREATE DATABASE %s WITH ('location'='%s')", flinkDatabase, location);
+    assertThat(validationNamespaceCatalog.namespaceExists(icebergNamespace))
+        .as("Namespace should exist")
+        .isTrue();
+    Map<String, String> nsMetadata =
+        validationNamespaceCatalog.loadNamespaceMetadata(icebergNamespace);
+    assertThat(nsMetadata).containsEntry("location", location.toString());
+  }
+}