This is an automated email from the ASF dual-hosted git repository.
fanng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 1ec5b1152 [#4581]feat(iceberg): support Gravitino-based multi catalog
support for Gravitino Iceberg REST server (#4598)
1ec5b1152 is described below
commit 1ec5b1152c30f53441f971066a818a5c6838a641
Author: theoryxu <[email protected]>
AuthorDate: Sun Aug 25 19:46:45 2024 +0800
[#4581]feat(iceberg): support Gravitino-based multi catalog support for
Gravitino Iceberg REST server (#4598)
### What changes were proposed in this pull request?
support Gravitino-based multi catalog support for Gravitino Iceberg REST
server
### Why are the changes needed?
fixes: #4581
### Does this PR introduce _any_ user-facing change?
add a property key
### How was this patch tested?
1. add UT
2. manual test
---------
Co-authored-by: theoryxu <[email protected]>
---
.../lakehouse/iceberg/IcebergConstants.java | 7 ++
docs/iceberg-rest-service.md | 21 +++-
.../gravitino/iceberg/common/IcebergConfig.java | 23 ++++
iceberg/iceberg-rest-server/build.gradle.kts | 4 +
.../org/apache/gravitino/iceberg/RESTService.java | 2 +-
.../ConfigBasedIcebergTableOpsProvider.java | 4 +-
.../GravitinoBasedIcebergTableOpsProvider.java | 98 +++++++++++++++++
.../iceberg/service}/IcebergTableOpsManager.java | 48 ++++++++-
.../service/rest/IcebergNamespaceOperations.java | 2 +-
.../service/rest/IcebergTableOperations.java | 2 +-
.../service/rest/IcebergTableRenameOperations.java | 2 +-
.../TestConfigBasedIcebergTableOpsProvider.java | 15 +--
.../TestGravitinoBasedIcebergTableOpsProvider.java | 120 +++++++++++++++++++++
.../service}/TestIcebergTableOpsManager.java | 9 +-
.../ConfigBasedIcebergTableOpsProviderForTest.java | 2 +-
.../iceberg/service/rest/IcebergRestTestUtil.java | 2 +-
16 files changed, 338 insertions(+), 23 deletions(-)
diff --git
a/catalogs/catalog-common/src/main/java/org/apache/gravitino/catalog/lakehouse/iceberg/IcebergConstants.java
b/catalogs/catalog-common/src/main/java/org/apache/gravitino/catalog/lakehouse/iceberg/IcebergConstants.java
index d07a6c487..21d5db3ff 100644
---
a/catalogs/catalog-common/src/main/java/org/apache/gravitino/catalog/lakehouse/iceberg/IcebergConstants.java
+++
b/catalogs/catalog-common/src/main/java/org/apache/gravitino/catalog/lakehouse/iceberg/IcebergConstants.java
@@ -65,7 +65,14 @@ public class IcebergConstants {
public static final String GRAVITINO_ICEBERG_REST_SERVICE_NAME =
"iceberg-rest";
+ public static final String ICEBERG_REST_CATALOG_CACHE_EVICTION_INTERVAL =
+ "catalog-cache-eviction-interval-ms";
+
public static final String ICEBERG_REST_CATALOG_PROVIDER =
"catalog-provider";
+ public static final String GRAVITINO_URI = "gravitino-uri";
+
+ public static final String GRAVITINO_METALAKE = "gravitino-metalake";
+
public static final String GRAVITINO_DEFAULT_CATALOG =
"__gravitino_default_catalog";
}
diff --git a/docs/iceberg-rest-service.md b/docs/iceberg-rest-service.md
index d87649404..67fb96dd4 100644
--- a/docs/iceberg-rest-service.md
+++ b/docs/iceberg-rest-service.md
@@ -178,7 +178,9 @@ The Gravitino Iceberg REST server supports multiple
catalogs and offers a config
|----------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------|----------|---------------|
| `gravitino.iceberg-rest.catalog-provider` | Catalog provider class name,
you can develop a class that implements `IcebergTableOpsProvider` and add the
corresponding jar file to the Iceberg REST service classpath directory. |
`config-based-provider` | No | 0.7.0 |
-When using a config-based catalog provider, you can configure the default
catalog with `gravitino.iceberg-rest.catalog.<param name>=<value>`. For
specific catalogs, use the format `gravitino.iceberg-rest.catalog.<catalog
name>.<param name>=<value>`.
+##### Configuration based catalog provider
+
+When using a configuration based catalog provider, you can configure the
default catalog with `gravitino.iceberg-rest.catalog.<param name>=<value>`. For
specific catalogs, use the format `gravitino.iceberg-rest.catalog.<catalog
name>.<param name>=<value>`.
For instance, you can configure three different catalogs, the default catalog
and the specific `hive_backend` and `jdbc_backend` catalogs separately.
@@ -215,6 +217,23 @@ You can access different catalogs by setting the `prefix`
to the specific catalo
...
```
+##### Gravitino server based catalog provider
+
+When using a Gravitino server based catalog provider, you can leverage
Gravitino to support dynamic catalog management for the Iceberg REST server.
+
+| Configuration item | Description
| Default value | Required |
Since Version |
+|--------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|---------------|----------|---------------|
+| `gravitino.iceberg-rest.gravitino-uri` | The uri of
Gravitino server address, only worked if `catalog-provider` is
`gravitino-based-provider`. | (none)
| No | 0.7.0 |
+| `gravitino.iceberg-rest.gravitino-metalake` | The metalake
name that `gravitino-based-provider` used to request to Gravitino, only worked
if `catalog-provider` is `gravitino-based-provider`. | (none) | No
| 0.7.0 |
+| `gravitino.iceberg-rest.catalog-cache-eviction-interval-ms` | Catalog cache
eviction interval.
| 3600000 | No |
0.7.0 |
+
+```text
+gravitino.iceberg-rest.catalog-cache-eviction-interval-ms = 300000
+gravitino.iceberg-rest.catalog-provider = gravitino-based-provider
+gravitino.iceberg-rest.gravitino-uri = http://127.0.0.1:8090
+gravitino.iceberg-rest.gravitino-metalake = test
+```
+
### Other Apache Iceberg catalog properties
You can add other properties defined in [Iceberg catalog
properties](https://iceberg.apache.org/docs/1.5.2/configuration/#catalog-properties).
diff --git
a/iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/IcebergConfig.java
b/iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/IcebergConfig.java
index bc1e47a06..e99d28508 100644
---
a/iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/IcebergConfig.java
+++
b/iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/IcebergConfig.java
@@ -166,6 +166,13 @@ public class IcebergConfig extends Config implements
OverwriteDefaultConfig {
.stringConf()
.create();
+ public static final ConfigEntry<Long>
ICEBERG_REST_CATALOG_CACHE_EVICTION_INTERVAL =
+ new
ConfigBuilder(IcebergConstants.ICEBERG_REST_CATALOG_CACHE_EVICTION_INTERVAL)
+ .doc("Catalog cache eviction interval.")
+ .version(ConfigConstants.VERSION_0_7_0)
+ .longConf()
+ .createWithDefault(3600000L);
+
public static final ConfigEntry<String> ICEBERG_REST_CATALOG_PROVIDER =
new ConfigBuilder(IcebergConstants.ICEBERG_REST_CATALOG_PROVIDER)
.doc(
@@ -174,6 +181,22 @@ public class IcebergConfig extends Config implements
OverwriteDefaultConfig {
.stringConf()
.createWithDefault("config-based-provider");
+ public static final ConfigEntry<String> GRAVITINO_URI =
+ new ConfigBuilder(IcebergConstants.GRAVITINO_URI)
+ .doc(
+ "The uri of Gravitino server address, only worked if
`catalog-provider` is `gravitino-based-provider`.")
+ .version(ConfigConstants.VERSION_0_7_0)
+ .stringConf()
+ .create();
+
+ public static final ConfigEntry<String> GRAVITINO_METALAKE =
+ new ConfigBuilder(IcebergConstants.GRAVITINO_METALAKE)
+ .doc(
+ "The metalake name that `gravitino-based-provider` used to
request to Gravitino, only worked if `catalog-provider` is
`gravitino-based-provider`.")
+ .version(ConfigConstants.VERSION_0_7_0)
+ .stringConf()
+ .create();
+
public String getJdbcDriver() {
return get(JDBC_DRIVER);
}
diff --git a/iceberg/iceberg-rest-server/build.gradle.kts
b/iceberg/iceberg-rest-server/build.gradle.kts
index 0fa77b850..0ee6b0ff6 100644
--- a/iceberg/iceberg-rest-server/build.gradle.kts
+++ b/iceberg/iceberg-rest-server/build.gradle.kts
@@ -31,7 +31,9 @@ val icebergVersion: String = libs.versions.iceberg.get()
val scalaCollectionCompatVersion: String =
libs.versions.scala.collection.compat.get()
dependencies {
+ implementation(project(":api"))
implementation(project(":catalogs:catalog-common"))
+ implementation(project(":clients:client-java"))
implementation(project(":core"))
implementation(project(":common"))
implementation(project(":iceberg:iceberg-common"))
@@ -40,6 +42,8 @@ dependencies {
implementation(libs.bundles.jetty)
implementation(libs.bundles.jersey)
implementation(libs.bundles.log4j)
+ implementation(libs.caffeine)
+ implementation(libs.commons.lang3)
implementation(libs.guava)
implementation(libs.jackson.annotations)
implementation(libs.jackson.databind)
diff --git
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/RESTService.java
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/RESTService.java
index dd3b9d9ab..d791a6a1c 100644
---
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/RESTService.java
+++
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/RESTService.java
@@ -23,9 +23,9 @@ import javax.servlet.Servlet;
import org.apache.gravitino.GravitinoEnv;
import org.apache.gravitino.auxiliary.GravitinoAuxiliaryService;
import org.apache.gravitino.iceberg.common.IcebergConfig;
-import org.apache.gravitino.iceberg.common.ops.IcebergTableOpsManager;
import org.apache.gravitino.iceberg.service.IcebergExceptionMapper;
import org.apache.gravitino.iceberg.service.IcebergObjectMapperProvider;
+import org.apache.gravitino.iceberg.service.IcebergTableOpsManager;
import org.apache.gravitino.iceberg.service.metrics.IcebergMetricsManager;
import org.apache.gravitino.metrics.MetricsSystem;
import org.apache.gravitino.metrics.source.MetricsSource;
diff --git
a/iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/ops/ConfigBasedIcebergTableOpsProvider.java
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/provider/ConfigBasedIcebergTableOpsProvider.java
similarity index 95%
rename from
iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/ops/ConfigBasedIcebergTableOpsProvider.java
rename to
iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/provider/ConfigBasedIcebergTableOpsProvider.java
index 070e67ce1..2cbf2af2c 100644
---
a/iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/ops/ConfigBasedIcebergTableOpsProvider.java
+++
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/provider/ConfigBasedIcebergTableOpsProvider.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.gravitino.iceberg.common.ops;
+package org.apache.gravitino.iceberg.provider;
import com.google.common.annotations.VisibleForTesting;
import java.util.Map;
@@ -24,6 +24,8 @@ import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
import org.apache.gravitino.iceberg.common.IcebergConfig;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOps;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOpsProvider;
import org.apache.gravitino.utils.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/provider/GravitinoBasedIcebergTableOpsProvider.java
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/provider/GravitinoBasedIcebergTableOpsProvider.java
new file mode 100644
index 000000000..a09abbb1a
--- /dev/null
+++
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/provider/GravitinoBasedIcebergTableOpsProvider.java
@@ -0,0 +1,98 @@
+/*
+ * 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.gravitino.iceberg.provider;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.gravitino.Catalog;
+import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
+import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergPropertiesUtils;
+import org.apache.gravitino.client.GravitinoAdminClient;
+import org.apache.gravitino.iceberg.common.IcebergConfig;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOps;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOpsProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This provider proxy Gravitino lakehouse-iceberg catalogs.
+ *
+ * <p>For example, there are one catalog named iceberg_catalog in metalake
+ *
+ * <p>The catalogName is iceberg_catalog
+ */
+public class GravitinoBasedIcebergTableOpsProvider
+ implements IcebergTableOpsProvider, AutoCloseable {
+ public static final Logger LOG =
+ LoggerFactory.getLogger(GravitinoBasedIcebergTableOpsProvider.class);
+
+ public static final String GRAVITINO_BASE_ICEBERG_TABLE_OPS_PROVIDER_NAME =
+ "gravitino-based-provider";
+
+ private String gravitinoMetalake;
+
+ private GravitinoAdminClient client;
+
+ @Override
+ public void initialize(Map<String, String> properties) {
+ String uri = properties.get(IcebergConstants.GRAVITINO_URI);
+ String metalake = properties.get(IcebergConstants.GRAVITINO_METALAKE);
+
+ Preconditions.checkArgument(
+ StringUtils.isNotBlank(uri), IcebergConstants.GRAVITINO_URI + " is
blank");
+ Preconditions.checkArgument(
+ StringUtils.isNotBlank(metalake), IcebergConstants.GRAVITINO_METALAKE
+ " is blank");
+
+ this.gravitinoMetalake = metalake;
+ this.client = GravitinoAdminClient.builder(uri).build();
+ }
+
+ @Override
+ public IcebergTableOps getIcebergTableOps(String catalogName) {
+ Preconditions.checkArgument(
+ StringUtils.isNotBlank(catalogName), "blank catalogName is illegal");
+ Preconditions.checkArgument(
+ !IcebergConstants.GRAVITINO_DEFAULT_CATALOG.equals(catalogName),
+ IcebergConstants.GRAVITINO_DEFAULT_CATALOG + " is illegal in
gravitino-based-provider");
+
+ Catalog catalog =
client.loadMetalake(gravitinoMetalake).loadCatalog(catalogName);
+
+ Preconditions.checkArgument(
+ "lakehouse-iceberg".equals(catalog.provider()),
+ String.format("%s.%s is not iceberg catalog", gravitinoMetalake,
catalogName));
+
+ Map<String, String> properties =
+
IcebergPropertiesUtils.toIcebergCatalogProperties(catalog.properties());
+ return new IcebergTableOps(new IcebergConfig(properties));
+ }
+
+ @VisibleForTesting
+ void setClient(GravitinoAdminClient client) {
+ this.client = client;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (client != null) {
+ client.close();
+ }
+ }
+}
diff --git
a/iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/ops/IcebergTableOpsManager.java
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/IcebergTableOpsManager.java
similarity index 67%
rename from
iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/ops/IcebergTableOpsManager.java
rename to
iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/IcebergTableOpsManager.java
index 57792b89f..906bb5b26 100644
---
a/iceberg/iceberg-common/src/main/java/org/apache/gravitino/iceberg/common/ops/IcebergTableOpsManager.java
+++
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/IcebergTableOpsManager.java
@@ -16,16 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.gravitino.iceberg.common.ops;
+package org.apache.gravitino.iceberg.service;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.Scheduler;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.Map;
-import org.apache.commons.lang.StringUtils;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import org.apache.commons.lang3.StringUtils;
import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
import org.apache.gravitino.iceberg.common.IcebergConfig;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOps;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOpsProvider;
+import
org.apache.gravitino.iceberg.provider.ConfigBasedIcebergTableOpsProvider;
+import
org.apache.gravitino.iceberg.provider.GravitinoBasedIcebergTableOpsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,16 +43,37 @@ public class IcebergTableOpsManager implements
AutoCloseable {
private static final ImmutableMap<String, String>
ICEBERG_TABLE_OPS_PROVIDER_NAMES =
ImmutableMap.of(
ConfigBasedIcebergTableOpsProvider.CONFIG_BASE_ICEBERG_TABLE_OPS_PROVIDER_NAME,
- ConfigBasedIcebergTableOpsProvider.class.getCanonicalName());
+ ConfigBasedIcebergTableOpsProvider.class.getCanonicalName(),
+
GravitinoBasedIcebergTableOpsProvider.GRAVITINO_BASE_ICEBERG_TABLE_OPS_PROVIDER_NAME,
+ GravitinoBasedIcebergTableOpsProvider.class.getCanonicalName());
private final Cache<String, IcebergTableOps> icebergTableOpsCache;
private final IcebergTableOpsProvider provider;
public IcebergTableOpsManager(Map<String, String> properties) {
- this.icebergTableOpsCache = Caffeine.newBuilder().build();
this.provider = createProvider(properties);
this.provider.initialize(properties);
+ this.icebergTableOpsCache =
+ Caffeine.newBuilder()
+ .expireAfterWrite(
+ (new IcebergConfig(properties))
+
.get(IcebergConfig.ICEBERG_REST_CATALOG_CACHE_EVICTION_INTERVAL),
+ TimeUnit.MILLISECONDS)
+ .removalListener(
+ (k, v, c) -> {
+ LOG.info("Remove IcebergTableOps cache {}.", k);
+ closeIcebergTableOps((IcebergTableOps) v);
+ })
+ .scheduler(
+ Scheduler.forScheduledExecutorService(
+ new ScheduledThreadPoolExecutor(
+ 1,
+ new ThreadFactoryBuilder()
+ .setDaemon(true)
+ .setNameFormat("table-ops-cleaner-%d")
+ .build())))
+ .build();
}
/**
@@ -97,8 +126,19 @@ public class IcebergTableOpsManager implements
AutoCloseable {
}
}
+ private void closeIcebergTableOps(IcebergTableOps ops) {
+ try {
+ ops.close();
+ } catch (Exception ex) {
+ LOG.warn("Close Iceberg table ops fail: {}, {}", ops, ex);
+ }
+ }
+
@Override
public void close() throws Exception {
icebergTableOpsCache.invalidateAll();
+ if (provider instanceof AutoCloseable) {
+ ((AutoCloseable) provider).close();
+ }
}
}
diff --git
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceOperations.java
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceOperations.java
index 82b6250e6..c9fd7a5c0 100644
---
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceOperations.java
+++
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceOperations.java
@@ -34,8 +34,8 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import org.apache.gravitino.iceberg.common.ops.IcebergTableOpsManager;
import org.apache.gravitino.iceberg.service.IcebergRestUtils;
+import org.apache.gravitino.iceberg.service.IcebergTableOpsManager;
import org.apache.gravitino.metrics.MetricNames;
import org.apache.iceberg.catalog.Namespace;
import org.apache.iceberg.rest.RESTUtil;
diff --git
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableOperations.java
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableOperations.java
index f6f6042a5..d028c8d4a 100644
---
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableOperations.java
+++
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableOperations.java
@@ -37,9 +37,9 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import org.apache.gravitino.iceberg.common.ops.IcebergTableOpsManager;
import org.apache.gravitino.iceberg.service.IcebergObjectMapper;
import org.apache.gravitino.iceberg.service.IcebergRestUtils;
+import org.apache.gravitino.iceberg.service.IcebergTableOpsManager;
import org.apache.gravitino.iceberg.service.metrics.IcebergMetricsManager;
import org.apache.gravitino.metrics.MetricNames;
import org.apache.iceberg.catalog.TableIdentifier;
diff --git
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableRenameOperations.java
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableRenameOperations.java
index 441ce0551..4fc2ea832 100644
---
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableRenameOperations.java
+++
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableRenameOperations.java
@@ -30,8 +30,8 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import org.apache.gravitino.iceberg.common.ops.IcebergTableOpsManager;
import org.apache.gravitino.iceberg.service.IcebergRestUtils;
+import org.apache.gravitino.iceberg.service.IcebergTableOpsManager;
import org.apache.gravitino.metrics.MetricNames;
import org.apache.iceberg.rest.requests.RenameTableRequest;
diff --git
a/iceberg/iceberg-common/src/test/java/org/apache/gravitino/iceberg/common/ops/TestConfigBasedIcebergTableOpsProvider.java
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/provider/TestConfigBasedIcebergTableOpsProvider.java
similarity index 90%
rename from
iceberg/iceberg-common/src/test/java/org/apache/gravitino/iceberg/common/ops/TestConfigBasedIcebergTableOpsProvider.java
rename to
iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/provider/TestConfigBasedIcebergTableOpsProvider.java
index c3c8c3fe8..70d9a834f 100644
---
a/iceberg/iceberg-common/src/test/java/org/apache/gravitino/iceberg/common/ops/TestConfigBasedIcebergTableOpsProvider.java
+++
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/provider/TestConfigBasedIcebergTableOpsProvider.java
@@ -16,13 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.gravitino.iceberg.common.ops;
+package org.apache.gravitino.iceberg.provider;
import com.google.common.collect.Maps;
import java.util.Map;
import java.util.UUID;
import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
import org.apache.gravitino.iceberg.common.IcebergConfig;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOps;
import org.apache.iceberg.hive.HiveCatalog;
import org.apache.iceberg.inmemory.InMemoryCatalog;
import org.apache.iceberg.jdbc.JdbcCatalog;
@@ -94,13 +95,13 @@ public class TestConfigBasedIcebergTableOpsProvider {
Assertions.assertEquals("memory",
defaultIcebergConfig.get(IcebergConfig.CATALOG_BACKEND));
Assertions.assertEquals("/tmp/",
defaultIcebergConfig.get(IcebergConfig.CATALOG_WAREHOUSE));
- Assertions.assertEquals(hiveCatalogName, hiveOps.catalog.name());
- Assertions.assertEquals(jdbcCatalogName, jdbcOps.catalog.name());
- Assertions.assertEquals(defaultCatalogName, defaultOps.catalog.name());
+ Assertions.assertEquals(hiveCatalogName, hiveOps.getCatalog().name());
+ Assertions.assertEquals(jdbcCatalogName, jdbcOps.getCatalog().name());
+ Assertions.assertEquals(defaultCatalogName,
defaultOps.getCatalog().name());
- Assertions.assertTrue(hiveOps.catalog instanceof HiveCatalog);
- Assertions.assertTrue(jdbcOps.catalog instanceof JdbcCatalog);
- Assertions.assertTrue(defaultOps.catalog instanceof InMemoryCatalog);
+ Assertions.assertTrue(hiveOps.getCatalog() instanceof HiveCatalog);
+ Assertions.assertTrue(jdbcOps.getCatalog() instanceof JdbcCatalog);
+ Assertions.assertTrue(defaultOps.getCatalog() instanceof InMemoryCatalog);
}
@ParameterizedTest
diff --git
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/provider/TestGravitinoBasedIcebergTableOpsProvider.java
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/provider/TestGravitinoBasedIcebergTableOpsProvider.java
new file mode 100644
index 000000000..b95a430f4
--- /dev/null
+++
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/provider/TestGravitinoBasedIcebergTableOpsProvider.java
@@ -0,0 +1,120 @@
+/*
+ * 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.gravitino.iceberg.provider;
+
+import java.util.HashMap;
+import java.util.UUID;
+import org.apache.gravitino.Catalog;
+import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
+import org.apache.gravitino.client.GravitinoAdminClient;
+import org.apache.gravitino.client.GravitinoMetalake;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOps;
+import org.apache.iceberg.hive.HiveCatalog;
+import org.apache.iceberg.jdbc.JdbcCatalog;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+public class TestGravitinoBasedIcebergTableOpsProvider {
+ private static final String STORE_PATH =
+ "/tmp/gravitino_test_iceberg_jdbc_backend_" +
UUID.randomUUID().toString().replace("-", "");
+
+ @Test
+ public void testValidIcebergTableOps() {
+ String hiveCatalogName = "hive_backend";
+ String jdbcCatalogName = "jdbc_backend";
+
+ Catalog hiveMockCatalog = Mockito.mock(Catalog.class);
+ Catalog jdbcMockCatalog = Mockito.mock(Catalog.class);
+
+ GravitinoMetalake gravitinoMetalake =
Mockito.mock(GravitinoMetalake.class);
+
Mockito.when(gravitinoMetalake.loadCatalog(hiveCatalogName)).thenReturn(hiveMockCatalog);
+
Mockito.when(gravitinoMetalake.loadCatalog(jdbcCatalogName)).thenReturn(jdbcMockCatalog);
+
+ Mockito.when(hiveMockCatalog.provider()).thenReturn("lakehouse-iceberg");
+ Mockito.when(jdbcMockCatalog.provider()).thenReturn("lakehouse-iceberg");
+
+ Mockito.when(hiveMockCatalog.properties())
+ .thenReturn(
+ new HashMap<String, String>() {
+ {
+ put(IcebergConstants.CATALOG_BACKEND, "hive");
+ put(IcebergConstants.URI, "thrift://127.0.0.1:7004");
+ put(IcebergConstants.WAREHOUSE, "/tmp/usr/hive/warehouse");
+ put(IcebergConstants.CATALOG_BACKEND_NAME, hiveCatalogName);
+ }
+ });
+ Mockito.when(jdbcMockCatalog.properties())
+ .thenReturn(
+ new HashMap<String, String>() {
+ {
+ put(IcebergConstants.CATALOG_BACKEND, "jdbc");
+ put(
+ IcebergConstants.URI,
+ String.format("jdbc:h2:%s;DB_CLOSE_DELAY=-1;MODE=MYSQL",
STORE_PATH));
+ put(IcebergConstants.WAREHOUSE,
"/tmp/user/hive/warehouse-jdbc");
+ put(IcebergConstants.GRAVITINO_JDBC_USER, "gravitino");
+ put(IcebergConstants.GRAVITINO_JDBC_PASSWORD, "gravitino");
+ put(IcebergConstants.GRAVITINO_JDBC_DRIVER, "org.h2.Driver");
+ put(IcebergConstants.ICEBERG_JDBC_INITIALIZE, "true");
+ put(IcebergConstants.CATALOG_BACKEND_NAME, jdbcCatalogName);
+ }
+ });
+
+ GravitinoBasedIcebergTableOpsProvider provider = new
GravitinoBasedIcebergTableOpsProvider();
+ GravitinoAdminClient client = Mockito.mock(GravitinoAdminClient.class);
+
Mockito.when(client.loadMetalake(Mockito.any())).thenReturn(gravitinoMetalake);
+ provider.setClient(client);
+
+ IcebergTableOps hiveOps = provider.getIcebergTableOps(hiveCatalogName);
+ IcebergTableOps jdbcOps = provider.getIcebergTableOps(jdbcCatalogName);
+
+ Assertions.assertEquals(hiveCatalogName, hiveOps.getCatalog().name());
+ Assertions.assertEquals(jdbcCatalogName, jdbcOps.getCatalog().name());
+
+ Assertions.assertTrue(hiveOps.getCatalog() instanceof HiveCatalog);
+ Assertions.assertTrue(jdbcOps.getCatalog() instanceof JdbcCatalog);
+ }
+
+ @Test
+ public void testInvalidIcebergTableOps() {
+ String invalidCatalogName = "invalid_catalog";
+
+ Catalog invalidCatalog = Mockito.mock(Catalog.class);
+
+ GravitinoMetalake gravitinoMetalake =
Mockito.mock(GravitinoMetalake.class);
+
Mockito.when(gravitinoMetalake.loadCatalog(invalidCatalogName)).thenReturn(invalidCatalog);
+
+ Mockito.when(invalidCatalog.provider()).thenReturn("hive");
+
+ GravitinoAdminClient client = Mockito.mock(GravitinoAdminClient.class);
+
Mockito.when(client.loadMetalake(Mockito.any())).thenReturn(gravitinoMetalake);
+
+ GravitinoBasedIcebergTableOpsProvider provider = new
GravitinoBasedIcebergTableOpsProvider();
+ provider.setClient(client);
+
+ Assertions.assertThrowsExactly(
+ IllegalArgumentException.class, () ->
provider.getIcebergTableOps(invalidCatalogName));
+ Assertions.assertThrowsExactly(
+ IllegalArgumentException.class, () -> provider.getIcebergTableOps(""));
+ Assertions.assertThrowsExactly(
+ IllegalArgumentException.class,
+ () ->
provider.getIcebergTableOps(IcebergConstants.GRAVITINO_DEFAULT_CATALOG));
+ }
+}
diff --git
a/iceberg/iceberg-common/src/test/java/org/apache/gravitino/iceberg/common/ops/TestIcebergTableOpsManager.java
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/TestIcebergTableOpsManager.java
similarity index 88%
rename from
iceberg/iceberg-common/src/test/java/org/apache/gravitino/iceberg/common/ops/TestIcebergTableOpsManager.java
rename to
iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/TestIcebergTableOpsManager.java
index 04ded71dd..68e03841f 100644
---
a/iceberg/iceberg-common/src/test/java/org/apache/gravitino/iceberg/common/ops/TestIcebergTableOpsManager.java
+++
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/TestIcebergTableOpsManager.java
@@ -16,11 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.gravitino.iceberg.common.ops;
+package org.apache.gravitino.iceberg.service;
import com.google.common.collect.Maps;
import java.util.Map;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.gravitino.iceberg.common.ops.IcebergTableOps;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -43,9 +44,9 @@ public class TestIcebergTableOpsManager {
IcebergTableOps ops = manager.getOps(rawPrefix);
if (StringUtils.isBlank(prefix)) {
- Assertions.assertEquals(ops.catalog.name(), DEFAULT_CATALOG);
+ Assertions.assertEquals(ops.getCatalog().name(), DEFAULT_CATALOG);
} else {
- Assertions.assertEquals(ops.catalog.name(), prefix);
+ Assertions.assertEquals(ops.getCatalog().name(), prefix);
}
}
diff --git
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/ConfigBasedIcebergTableOpsProviderForTest.java
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/ConfigBasedIcebergTableOpsProviderForTest.java
index 6a9375615..07ef96d20 100644
---
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/ConfigBasedIcebergTableOpsProviderForTest.java
+++
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/ConfigBasedIcebergTableOpsProviderForTest.java
@@ -18,8 +18,8 @@
*/
package org.apache.gravitino.iceberg.service.rest;
-import
org.apache.gravitino.iceberg.common.ops.ConfigBasedIcebergTableOpsProvider;
import org.apache.gravitino.iceberg.common.ops.IcebergTableOps;
+import
org.apache.gravitino.iceberg.provider.ConfigBasedIcebergTableOpsProvider;
public class ConfigBasedIcebergTableOpsProviderForTest extends
ConfigBasedIcebergTableOpsProvider {
@Override
diff --git
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergRestTestUtil.java
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergRestTestUtil.java
index e7b19e0af..ab36d1924 100644
---
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergRestTestUtil.java
+++
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergRestTestUtil.java
@@ -25,9 +25,9 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
import org.apache.gravitino.iceberg.common.IcebergConfig;
-import org.apache.gravitino.iceberg.common.ops.IcebergTableOpsManager;
import org.apache.gravitino.iceberg.service.IcebergExceptionMapper;
import org.apache.gravitino.iceberg.service.IcebergObjectMapperProvider;
+import org.apache.gravitino.iceberg.service.IcebergTableOpsManager;
import org.apache.gravitino.iceberg.service.metrics.IcebergMetricsManager;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.jackson.JacksonFeature;