This is an automated email from the ASF dual-hosted git repository.
nathanma pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/amoro.git
The following commit(s) were added to refs/heads/master by this push:
new f5b0ac564 [Feature]: unify filesystem alias and add metastore matrix
apis (#4060)
f5b0ac564 is described below
commit f5b0ac5641942368b8fb763ab2ba85f570529355
Author: nathan.ma <[email protected]>
AuthorDate: Mon Jan 26 16:46:01 2026 +0800
[Feature]: unify filesystem alias and add metastore matrix apis (#4060)
* [Feature]: unify filesystem alias and add metastore matrix apis
* spotless
* fix ci
---------
Co-authored-by: majin.nathan <[email protected]>
---
.../amoro/server/catalog/CatalogBuilder.java | 5 +
.../server/catalog/DefaultCatalogManager.java | 5 +-
.../amoro/server/dashboard/DashboardServer.java | 2 +
.../dashboard/controller/CatalogController.java | 59 +++++-
.../amoro/server/terminal/TerminalManager.java | 13 +-
.../org/apache/amoro/CommonUnifiedCatalog.java | 9 +-
.../amoro/properties/CatalogMetaProperties.java | 9 +-
.../java/org/apache/amoro/utils/CatalogUtil.java | 195 ++++++++++++-------
.../amoro/formats/hudi/HudiCatalogFactory.java | 3 +-
.../formats/mixed/MixedIcebergCatalogFactory.java | 3 +-
.../java/org/apache/amoro/mixed/CatalogLoader.java | 3 +-
.../apache/amoro/utils/MixedFormatCatalogUtil.java | 3 +-
amoro-web/src/services/setting.services.ts | 6 +
amoro-web/src/views/catalogs/Detail.vue | 215 +++++++++------------
.../src/views/tables/components/TableExplorer.vue | 2 +-
amoro-web/src/views/tables/index.vue | 5 +
16 files changed, 316 insertions(+), 221 deletions(-)
diff --git
a/amoro-ams/src/main/java/org/apache/amoro/server/catalog/CatalogBuilder.java
b/amoro-ams/src/main/java/org/apache/amoro/server/catalog/CatalogBuilder.java
index d405bc1c3..31c8240ca 100644
---
a/amoro-ams/src/main/java/org/apache/amoro/server/catalog/CatalogBuilder.java
+++
b/amoro-ams/src/main/java/org/apache/amoro/server/catalog/CatalogBuilder.java
@@ -20,6 +20,7 @@ package org.apache.amoro.server.catalog;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_AMS;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_CUSTOM;
+import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_FILESYSTEM;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_GLUE;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_HADOOP;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_HIVE;
@@ -42,6 +43,9 @@ public class CatalogBuilder {
private static final Map<String, Set<TableFormat>> formatSupportedMatrix =
ImmutableMap.of(
CATALOG_TYPE_HADOOP,
+ Sets.newHashSet(
+ TableFormat.ICEBERG, TableFormat.MIXED_ICEBERG,
TableFormat.PAIMON, TableFormat.HUDI),
+ CATALOG_TYPE_FILESYSTEM,
Sets.newHashSet(
TableFormat.ICEBERG, TableFormat.MIXED_ICEBERG,
TableFormat.PAIMON, TableFormat.HUDI),
CATALOG_TYPE_GLUE,
@@ -77,6 +81,7 @@ public class CatalogBuilder {
switch (type) {
case CATALOG_TYPE_HADOOP:
+ case CATALOG_TYPE_FILESYSTEM:
case CATALOG_TYPE_GLUE:
case CATALOG_TYPE_REST:
case CATALOG_TYPE_CUSTOM:
diff --git
a/amoro-ams/src/main/java/org/apache/amoro/server/catalog/DefaultCatalogManager.java
b/amoro-ams/src/main/java/org/apache/amoro/server/catalog/DefaultCatalogManager.java
index 1c3dc52a5..ce56959be 100644
---
a/amoro-ams/src/main/java/org/apache/amoro/server/catalog/DefaultCatalogManager.java
+++
b/amoro-ams/src/main/java/org/apache/amoro/server/catalog/DefaultCatalogManager.java
@@ -40,6 +40,7 @@ import
org.apache.amoro.shade.guava32.com.google.common.cache.CacheLoader;
import org.apache.amoro.shade.guava32.com.google.common.cache.LoadingCache;
import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
import org.apache.amoro.table.TableIdentifier;
+import org.apache.amoro.utils.CatalogUtil;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -230,7 +231,9 @@ public class DefaultCatalogManager extends PersistentBase
implements CatalogMana
}
private void validateCatalogUpdate(CatalogMeta oldMeta, CatalogMeta newMeta)
{
- if (!oldMeta.getCatalogType().equals(newMeta.getCatalogType())) {
+ String oldType =
CatalogUtil.normalizeMetastoreType(oldMeta.getCatalogType());
+ String newType =
CatalogUtil.normalizeMetastoreType(newMeta.getCatalogType());
+ if (!oldType.equals(newType)) {
throw new IllegalMetadataException("Cannot update catalog type");
}
}
diff --git
a/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/DashboardServer.java
b/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/DashboardServer.java
index 5233b7676..e465e65e7 100644
---
a/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/DashboardServer.java
+++
b/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/DashboardServer.java
@@ -299,6 +299,8 @@ public class DashboardServer {
get("", tableController::getCatalogs);
post("", catalogController::createCatalog);
get("metastore/types", catalogController::getCatalogTypeList);
+ get("metastore/{type}/table-formats",
catalogController::getMetastoreTableFormats);
+ get("metastore/{type}/storage-types",
catalogController::getMetastoreStorageTypes);
get("/{catalogName}", catalogController::getCatalogDetail);
delete("/{catalogName}", catalogController::deleteCatalog);
put("/{catalogName}", catalogController::updateCatalog);
diff --git
a/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/controller/CatalogController.java
b/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/controller/CatalogController.java
index 8a316e15f..d688f9e29 100644
---
a/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/controller/CatalogController.java
+++
b/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/controller/CatalogController.java
@@ -35,6 +35,7 @@ import static
org.apache.amoro.properties.CatalogMetaProperties.AUTH_CONFIGS_VAL
import static
org.apache.amoro.properties.CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_SIMPLE;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_AMS;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_CUSTOM;
+import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_FILESYSTEM;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_GLUE;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_HADOOP;
import static
org.apache.amoro.properties.CatalogMetaProperties.CATALOG_TYPE_HIVE;
@@ -48,6 +49,7 @@ import static
org.apache.amoro.properties.CatalogMetaProperties.STORAGE_CONFIGS_
import static
org.apache.amoro.properties.CatalogMetaProperties.STORAGE_CONFIGS_KEY_S3_ENDPOINT;
import static
org.apache.amoro.properties.CatalogMetaProperties.STORAGE_CONFIGS_KEY_TYPE;
import static
org.apache.amoro.properties.CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP;
+import static
org.apache.amoro.properties.CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_LOCAL;
import static
org.apache.amoro.properties.CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_OSS;
import static
org.apache.amoro.properties.CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_S3;
import static org.apache.amoro.properties.CatalogMetaProperties.TABLE_FORMATS;
@@ -106,6 +108,8 @@ public class CatalogController {
CATALOG_REQUIRED_PROPERTIES.put(CATALOG_TYPE_AMS,
Lists.newArrayList(KEY_WAREHOUSE));
CATALOG_REQUIRED_PROPERTIES.put(
CATALOG_TYPE_HADOOP,
Lists.newArrayList(CatalogProperties.WAREHOUSE_LOCATION));
+ CATALOG_REQUIRED_PROPERTIES.put(
+ CATALOG_TYPE_FILESYSTEM,
Lists.newArrayList(CatalogProperties.WAREHOUSE_LOCATION));
CATALOG_REQUIRED_PROPERTIES.put(
CATALOG_TYPE_GLUE,
Lists.newArrayList(CatalogProperties.WAREHOUSE_LOCATION));
CATALOG_REQUIRED_PROPERTIES.put(
@@ -146,6 +150,17 @@ public class CatalogController {
CatalogDescriptor.of(CATALOG_TYPE_HADOOP,
STORAGE_CONFIGS_VALUE_TYPE_HADOOP, PAIMON));
VALIDATE_CATALOGS.add(
CatalogDescriptor.of(CATALOG_TYPE_HADOOP,
STORAGE_CONFIGS_VALUE_TYPE_S3, PAIMON));
+ VALIDATE_CATALOGS.add(
+ CatalogDescriptor.of(
+ CATALOG_TYPE_FILESYSTEM, STORAGE_CONFIGS_VALUE_TYPE_HADOOP,
MIXED_ICEBERG));
+ VALIDATE_CATALOGS.add(
+ CatalogDescriptor.of(CATALOG_TYPE_FILESYSTEM,
STORAGE_CONFIGS_VALUE_TYPE_HADOOP, ICEBERG));
+ VALIDATE_CATALOGS.add(
+ CatalogDescriptor.of(CATALOG_TYPE_FILESYSTEM,
STORAGE_CONFIGS_VALUE_TYPE_LOCAL, ICEBERG));
+ VALIDATE_CATALOGS.add(
+ CatalogDescriptor.of(CATALOG_TYPE_FILESYSTEM,
STORAGE_CONFIGS_VALUE_TYPE_HADOOP, PAIMON));
+ VALIDATE_CATALOGS.add(
+ CatalogDescriptor.of(CATALOG_TYPE_FILESYSTEM,
STORAGE_CONFIGS_VALUE_TYPE_S3, PAIMON));
VALIDATE_CATALOGS.add(
CatalogDescriptor.of(CATALOG_TYPE_GLUE, STORAGE_CONFIGS_VALUE_TYPE_S3,
ICEBERG));
VALIDATE_CATALOGS.add(
@@ -156,6 +171,8 @@ public class CatalogController {
CatalogDescriptor.of(CATALOG_TYPE_CUSTOM,
STORAGE_CONFIGS_VALUE_TYPE_HADOOP, ICEBERG));
VALIDATE_CATALOGS.add(
CatalogDescriptor.of(CATALOG_TYPE_HADOOP,
STORAGE_CONFIGS_VALUE_TYPE_OSS, PAIMON));
+ VALIDATE_CATALOGS.add(
+ CatalogDescriptor.of(CATALOG_TYPE_FILESYSTEM,
STORAGE_CONFIGS_VALUE_TYPE_OSS, PAIMON));
VALIDATE_CATALOGS.add(
CatalogDescriptor.of(CATALOG_TYPE_GLUE,
STORAGE_CONFIGS_VALUE_TYPE_OSS, ICEBERG));
VALIDATE_CATALOGS.add(
@@ -232,9 +249,9 @@ public class CatalogController {
List<ImmutableMap<String, String>> catalogTypes = new ArrayList<>();
String valueKey = "value";
String displayKey = "display";
- catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_AMS, displayKey,
"Amoro Metastore"));
- catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_HIVE, displayKey,
"Hive Metastore"));
- catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_HADOOP,
displayKey, "Filesystem"));
+ catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_AMS, displayKey,
"Internal"));
+ catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_HIVE, displayKey,
"Hive"));
+ catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_FILESYSTEM,
displayKey, "FileSystem"));
catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_GLUE, displayKey,
"Glue"));
catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_REST, displayKey,
"REST"));
catalogTypes.add(ImmutableMap.of(valueKey, CATALOG_TYPE_CUSTOM,
displayKey, "Custom"));
@@ -432,14 +449,15 @@ public class CatalogController {
private CatalogMeta constructCatalogMeta(CatalogRegisterInfo info,
CatalogMeta oldCatalogMeta) {
CatalogMeta catalogMeta = new CatalogMeta();
catalogMeta.setCatalogName(info.getName());
- catalogMeta.setCatalogType(info.getType());
+ String metastoreType = CatalogUtil.normalizeMetastoreType(info.getType());
+ catalogMeta.setCatalogType(metastoreType);
catalogMeta.setCatalogProperties(
PropertiesUtil.unionCatalogProperties(info.getTableProperties(),
info.getProperties()));
// fill catalog impl when catalog type is glue or rest
- if (CatalogMetaProperties.CATALOG_TYPE_GLUE.equals(info.getType())) {
+ if (CatalogMetaProperties.CATALOG_TYPE_GLUE.equals(metastoreType)) {
catalogMeta.putToCatalogProperties(
CatalogProperties.CATALOG_IMPL, GlueCatalog.class.getName());
- } else if (CatalogMetaProperties.CATALOG_TYPE_REST.equals(info.getType()))
{
+ } else if (CatalogMetaProperties.CATALOG_TYPE_REST.equals(metastoreType)) {
catalogMeta.putToCatalogProperties(
CatalogProperties.CATALOG_IMPL, RESTCatalog.class.getName());
}
@@ -519,6 +537,8 @@ public class CatalogController {
STORAGE_CONFIGS_KEY_OSS_ENDPOINT,
"fs.oss.endpoint");
}
+ } else if (storageType.equals(STORAGE_CONFIGS_VALUE_TYPE_LOCAL)) {
+ // Local storage type does not require additional storage configs.
} else {
throw new RuntimeException("Invalid storage type " + storageType);
}
@@ -622,12 +642,11 @@ public class CatalogController {
if (catalogService.catalogExist(catalogName)) {
info.setName(catalogMeta.getCatalogName());
- // We create ams catalog with type hadoop in v0.3, we should be
compatible with it.
if (CATALOG_TYPE_HADOOP.equals(catalogMeta.getCatalogType())
&& !catalogMeta.getCatalogProperties().containsKey(TABLE_FORMATS)) {
info.setType(CATALOG_TYPE_AMS);
} else {
- info.setType(catalogMeta.getCatalogType());
+
info.setType(CatalogUtil.normalizeMetastoreType(catalogMeta.getCatalogType()));
}
// we put the table format single
@@ -732,6 +751,30 @@ public class CatalogController {
}
}
+ public void getMetastoreTableFormats(Context ctx) {
+ String metastoreType = ctx.pathParam("type");
+ String normalizedType = CatalogUtil.normalizeMetastoreType(metastoreType);
+ List<String> tableFormats =
+ VALIDATE_CATALOGS.stream()
+ .filter(d -> d.catalogType.equalsIgnoreCase(normalizedType))
+ .map(d -> d.tableFormat.name())
+ .distinct()
+ .collect(Collectors.toList());
+ ctx.json(OkResponse.of(tableFormats));
+ }
+
+ public void getMetastoreStorageTypes(Context ctx) {
+ String metastoreType = ctx.pathParam("type");
+ String normalizedType = CatalogUtil.normalizeMetastoreType(metastoreType);
+ List<String> storageTypes =
+ VALIDATE_CATALOGS.stream()
+ .filter(d -> d.catalogType.equalsIgnoreCase(normalizedType))
+ .map(d -> d.storageType)
+ .distinct()
+ .collect(Collectors.toList());
+ ctx.json(OkResponse.of(storageTypes));
+ }
+
private static class CatalogDescriptor {
private final String catalogType;
private final String storageType;
diff --git
a/amoro-ams/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
b/amoro-ams/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
index 2596d0428..4ab386bf0 100644
---
a/amoro-ams/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
+++
b/amoro-ams/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
@@ -37,6 +37,7 @@ import
org.apache.amoro.shade.guava32.com.google.common.collect.Lists;
import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
import org.apache.amoro.table.TableMetaStore;
import org.apache.amoro.utils.CatalogUtil;
+import org.apache.hadoop.conf.Configuration;
import org.apache.iceberg.CatalogProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -250,7 +251,7 @@ public class TerminalManager {
// ========================== private method =========================
private String catalogConnectorType(CatalogMeta catalogMeta) {
- String catalogType = catalogMeta.getCatalogType();
+ String catalogType =
CatalogUtil.normalizeCatalogType(catalogMeta.getCatalogType());
Set<TableFormat> tableFormatSet = CatalogUtil.tableFormats(catalogMeta);
if (catalogType.equalsIgnoreCase(CatalogType.AMS.name())) {
if (tableFormatSet.size() > 1) {
@@ -301,8 +302,12 @@ public class TerminalManager {
TableMetaStore.Builder builder = TableMetaStore.builder();
if (catalogMeta.getStorageConfigs() != null) {
Map<String, String> storageConfigs = catalogMeta.getStorageConfigs();
- if
(CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP.equalsIgnoreCase(
- CatalogUtil.getCompatibleStorageType(storageConfigs))) {
+ String storageType =
CatalogUtil.getCompatibleStorageType(storageConfigs);
+ if
(CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_LOCAL.equalsIgnoreCase(storageType))
{
+ builder.withConfiguration(new Configuration());
+ return builder.build();
+ }
+ if
(CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP.equalsIgnoreCase(storageType))
{
builder
.withBase64MetaStoreSite(
catalogMeta
@@ -388,7 +393,7 @@ public class TerminalManager {
private void applyClientProperties(CatalogMeta catalogMeta) {
Set<TableFormat> formats = CatalogUtil.tableFormats(catalogMeta);
- String catalogType = catalogMeta.getCatalogType();
+ String catalogType =
CatalogUtil.normalizeCatalogType(catalogMeta.getCatalogType());
if (formats.contains(TableFormat.ICEBERG)) {
if
(CatalogMetaProperties.CATALOG_TYPE_AMS.equalsIgnoreCase(catalogType)) {
catalogMeta.putToCatalogProperties(
diff --git
a/amoro-common/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
b/amoro-common/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
index 573cf42a0..b631c595f 100644
--- a/amoro-common/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
+++ b/amoro-common/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
@@ -202,14 +202,17 @@ public class CommonUnifiedCatalog implements
UnifiedCatalog {
protected void initializeFormatCatalogs() {
ServiceLoader<FormatCatalogFactory> loader =
ServiceLoader.load(FormatCatalogFactory.class);
- Set<TableFormat> formats = CatalogUtil.tableFormats(metaStoreType,
catalogProperties);
+ String normalizedMetastoreType =
CatalogUtil.normalizeMetastoreType(metaStoreType);
+ Set<TableFormat> formats =
CatalogUtil.tableFormats(normalizedMetastoreType, catalogProperties);
Map<TableFormat, FormatCatalog> formatCatalogs = Maps.newConcurrentMap();
for (FormatCatalogFactory factory : loader) {
if (formats.contains(factory.format())) {
Map<String, String> formatCatalogProperties =
- factory.convertCatalogProperties(name(), metaStoreType,
this.catalogProperties);
+ factory.convertCatalogProperties(
+ name(), normalizedMetastoreType, this.catalogProperties);
FormatCatalog catalog =
- factory.create(name(), metaStoreType, formatCatalogProperties,
tableMetaStore);
+ factory.create(
+ name(), normalizedMetastoreType, formatCatalogProperties,
tableMetaStore);
formatCatalogs.put(factory.format(), catalog);
}
}
diff --git
a/amoro-common/src/main/java/org/apache/amoro/properties/CatalogMetaProperties.java
b/amoro-common/src/main/java/org/apache/amoro/properties/CatalogMetaProperties.java
index 875a7c0f3..10f055b80 100644
---
a/amoro-common/src/main/java/org/apache/amoro/properties/CatalogMetaProperties.java
+++
b/amoro-common/src/main/java/org/apache/amoro/properties/CatalogMetaProperties.java
@@ -33,6 +33,7 @@ public class CatalogMetaProperties {
public static final String STORAGE_CONFIGS_VALUE_TYPE_HADOOP = "Hadoop";
public static final String STORAGE_CONFIGS_VALUE_TYPE_S3 = "S3";
public static final String STORAGE_CONFIGS_VALUE_TYPE_OSS = "OSS";
+ public static final String STORAGE_CONFIGS_VALUE_TYPE_LOCAL = "Local";
public static final String AUTH_CONFIGS_KEY_TYPE = "auth.type";
public static final String AUTH_CONFIGS_KEY_PRINCIPAL =
"auth.kerberos.principal";
@@ -53,7 +54,13 @@ public class CatalogMetaProperties {
public static final String KEY_TABLE_FILTER = "table-filter";
- public static final String CATALOG_TYPE_HADOOP = "hadoop";
+ /**
+ * Use {@link #CATALOG_TYPE_FILESYSTEM} instead for front But we can't
remove this until we could
+ * use filesystem and storage to determine the right catalog-impl
+ */
+ @Deprecated public static final String CATALOG_TYPE_HADOOP = "hadoop";
+
+ public static final String CATALOG_TYPE_FILESYSTEM = "filesystem";
public static final String CATALOG_TYPE_HIVE = "hive";
public static final String CATALOG_TYPE_AMS = "ams";
public static final String CATALOG_TYPE_GLUE = "glue";
diff --git a/amoro-common/src/main/java/org/apache/amoro/utils/CatalogUtil.java
b/amoro-common/src/main/java/org/apache/amoro/utils/CatalogUtil.java
index 862ca8516..19694f835 100644
--- a/amoro-common/src/main/java/org/apache/amoro/utils/CatalogUtil.java
+++ b/amoro-common/src/main/java/org/apache/amoro/utils/CatalogUtil.java
@@ -27,12 +27,14 @@ import
org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
import org.apache.amoro.table.TableIdentifier;
import org.apache.amoro.table.TableMetaStore;
import org.apache.commons.lang3.StringUtils;
+import org.apache.hadoop.conf.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -48,30 +50,40 @@ public class CatalogUtil {
/** Return table format set catalog supported. */
public static Set<TableFormat> tableFormats(
String metastoreType, Map<String, String> catalogProperties) {
+ Set<TableFormat> parsedFormats = null;
if (catalogProperties != null
&& catalogProperties.containsKey(CatalogMetaProperties.TABLE_FORMATS))
{
String tableFormatsProperty =
catalogProperties.get(CatalogMetaProperties.TABLE_FORMATS);
- return Arrays.stream(tableFormatsProperty.split(","))
- .map(
- tableFormatString ->
-
TableFormat.valueOf(tableFormatString.trim().toUpperCase(Locale.ROOT)))
- .collect(Collectors.toSet());
- } else {
- // Generate table format from catalog type for compatibility with older
versions
- switch (metastoreType) {
- case CatalogMetaProperties.CATALOG_TYPE_AMS:
- return Sets.newHashSet(TableFormat.MIXED_ICEBERG);
- case CatalogMetaProperties.CATALOG_TYPE_CUSTOM:
- case CatalogMetaProperties.CATALOG_TYPE_REST:
- case CatalogMetaProperties.CATALOG_TYPE_HADOOP:
- case CatalogMetaProperties.CATALOG_TYPE_GLUE:
- return Sets.newHashSet(TableFormat.ICEBERG);
- case CatalogMetaProperties.CATALOG_TYPE_HIVE:
- return Sets.newHashSet(TableFormat.MIXED_HIVE);
- default:
- throw new IllegalArgumentException("Unsupported catalog type:" +
metastoreType);
+ if (tableFormatsProperty != null) {
+ parsedFormats =
+ Arrays.stream(tableFormatsProperty.split(","))
+ .map(String::trim)
+ .filter(s -> !s.isEmpty())
+ .map(s -> TableFormat.valueOf(s.toUpperCase(Locale.ROOT)))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
}
}
+
+ if (parsedFormats != null && !parsedFormats.isEmpty()) {
+ return parsedFormats;
+ }
+
+ // Generate table format from catalog type for compatibility with older
versions
+ switch (metastoreType) {
+ case CatalogMetaProperties.CATALOG_TYPE_AMS:
+ return Sets.newHashSet(TableFormat.MIXED_ICEBERG);
+ case CatalogMetaProperties.CATALOG_TYPE_CUSTOM:
+ case CatalogMetaProperties.CATALOG_TYPE_REST:
+ case CatalogMetaProperties.CATALOG_TYPE_HADOOP:
+ case CatalogMetaProperties.CATALOG_TYPE_FILESYSTEM:
+ case CatalogMetaProperties.CATALOG_TYPE_GLUE:
+ return Sets.newHashSet(TableFormat.ICEBERG);
+ case CatalogMetaProperties.CATALOG_TYPE_HIVE:
+ return Sets.newHashSet(TableFormat.MIXED_HIVE);
+ default:
+ throw new IllegalArgumentException("Unsupported catalog type:" +
metastoreType);
+ }
}
/** Merge catalog properties in client side into catalog meta. */
@@ -111,10 +123,13 @@ public class CatalogUtil {
public static TableMetaStore buildMetaStore(CatalogMeta catalogMeta) {
// load storage configs
TableMetaStore.Builder builder = TableMetaStore.builder();
+ boolean isLocalStorage = false;
if (catalogMeta.getStorageConfigs() != null) {
Map<String, String> storageConfigs = catalogMeta.getStorageConfigs();
- if
(CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP.equalsIgnoreCase(
- CatalogUtil.getCompatibleStorageType(storageConfigs))) {
+ String storageType =
CatalogUtil.getCompatibleStorageType(storageConfigs);
+ isLocalStorage =
+
CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_LOCAL.equalsIgnoreCase(storageType);
+ if
(CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP.equalsIgnoreCase(storageType))
{
String coreSite =
storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_CORE_SITE);
String hdfsSite =
storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_HDFS_SITE);
String hiveSite =
storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_HIVE_SITE);
@@ -122,72 +137,77 @@ public class CatalogUtil {
.withBase64CoreSite(coreSite)
.withBase64MetaStoreSite(hiveSite)
.withBase64HdfsSite(hdfsSite);
+ } else if (isLocalStorage) {
+ builder.withConfiguration(new Configuration());
}
}
- boolean loadAuthFromAMS =
- propertyAsBoolean(
- catalogMeta.getCatalogProperties(),
- CatalogMetaProperties.LOAD_AUTH_FROM_AMS,
- CatalogMetaProperties.LOAD_AUTH_FROM_AMS_DEFAULT);
- // load auth configs from ams
- if (loadAuthFromAMS) {
- if (catalogMeta.getAuthConfigs() != null) {
- Map<String, String> authConfigs = catalogMeta.getAuthConfigs();
- String authType =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_TYPE);
- LOG.info("TableMetaStore use auth config in catalog meta, authType is
{}", authType);
+ if (!isLocalStorage) {
+ boolean loadAuthFromAMS =
+ propertyAsBoolean(
+ catalogMeta.getCatalogProperties(),
+ CatalogMetaProperties.LOAD_AUTH_FROM_AMS,
+ CatalogMetaProperties.LOAD_AUTH_FROM_AMS_DEFAULT);
+ // load auth configs from ams
+ if (loadAuthFromAMS) {
+ if (catalogMeta.getAuthConfigs() != null) {
+ Map<String, String> authConfigs = catalogMeta.getAuthConfigs();
+ String authType =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_TYPE);
+ LOG.info("TableMetaStore use auth config in catalog meta, authType
is {}", authType);
+ if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_SIMPLE.equalsIgnoreCase(authType))
{
+ String hadoopUsername =
+
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_HADOOP_USERNAME);
+ builder.withSimpleAuth(hadoopUsername);
+ } else if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_KERBEROS.equalsIgnoreCase(
+ authType)) {
+ String krb5 =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KRB5);
+ String keytab =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KEYTAB);
+ String principal =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_PRINCIPAL);
+ builder.withBase64KrbAuth(keytab, krb5, principal);
+ } else if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_AK_SK.equalsIgnoreCase(
+ authType)) {
+ String accessKey =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_ACCESS_KEY);
+ String secretKey =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_SECRET_KEY);
+ builder.withAkSkAuth(accessKey, secretKey);
+ }
+ }
+ }
+
+ // cover auth configs from ams with auth configs in properties
+ String authType =
+
catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_TYPE);
+ if (StringUtils.isNotEmpty(authType)) {
+ LOG.info("TableMetaStore use auth config in properties, authType is
{}", authType);
if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_SIMPLE.equalsIgnoreCase(authType))
{
String hadoopUsername =
-
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_HADOOP_USERNAME);
+ catalogMeta
+ .getCatalogProperties()
+ .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_HADOOP_USERNAME);
builder.withSimpleAuth(hadoopUsername);
} else if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_KERBEROS.equalsIgnoreCase(
authType)) {
- String krb5 =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KRB5);
- String keytab =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KEYTAB);
- String principal =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_PRINCIPAL);
+ String krb5 =
+
catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KRB5);
+ String keytab =
+
catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KEYTAB);
+ String principal =
+ catalogMeta
+ .getCatalogProperties()
+ .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_PRINCIPAL);
builder.withBase64KrbAuth(keytab, krb5, principal);
} else if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_AK_SK.equalsIgnoreCase(authType))
{
- String accessKey =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_ACCESS_KEY);
- String secretKey =
authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_SECRET_KEY);
+ String accessKey =
+ catalogMeta
+ .getCatalogProperties()
+ .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_ACCESS_KEY);
+ String secretKey =
+ catalogMeta
+ .getCatalogProperties()
+ .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_SECRET_KEY);
builder.withAkSkAuth(accessKey, secretKey);
}
}
}
-
- // cover auth configs from ams with auth configs in properties
- String authType =
-
catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_TYPE);
- if (StringUtils.isNotEmpty(authType)) {
- LOG.info("TableMetaStore use auth config in properties, authType is {}",
authType);
- if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_SIMPLE.equalsIgnoreCase(authType))
{
- String hadoopUsername =
- catalogMeta
- .getCatalogProperties()
- .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_HADOOP_USERNAME);
- builder.withSimpleAuth(hadoopUsername);
- } else if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_KERBEROS.equalsIgnoreCase(
- authType)) {
- String krb5 =
-
catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KRB5);
- String keytab =
-
catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KEYTAB);
- String principal =
- catalogMeta
- .getCatalogProperties()
- .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_PRINCIPAL);
- builder.withBase64KrbAuth(keytab, krb5, principal);
- } else if
(CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_AK_SK.equalsIgnoreCase(authType))
{
- String accessKey =
- catalogMeta
- .getCatalogProperties()
- .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_ACCESS_KEY);
- String secretKey =
- catalogMeta
- .getCatalogProperties()
- .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_SECRET_KEY);
- builder.withAkSkAuth(accessKey, secretKey);
- }
- }
return builder.build();
}
@@ -238,6 +258,35 @@ public class CatalogUtil {
}
}
+ public static String normalizeMetastoreType(String type) {
+ if (type == null) {
+ return null;
+ }
+ if (CatalogMetaProperties.CATALOG_TYPE_HADOOP.equalsIgnoreCase(type)
+ ||
CatalogMetaProperties.CATALOG_TYPE_FILESYSTEM.equalsIgnoreCase(type)) {
+ return CatalogMetaProperties.CATALOG_TYPE_FILESYSTEM;
+ }
+ return type;
+ }
+
+ /**
+ * Normalize catalog type for client-side and factory usage.
+ *
+ * <p>Iceberg only recognizes short catalog types like "hadoop" or "hive" in
its {@code
+ * CatalogUtil}, and does not recognize "filesystem" yet. To keep AMS using
"filesystem" in
+ * metadata while still working with Iceberg, we normalize "filesystem" back
to "hadoop" before
+ * passing it down to Iceberg.
+ */
+ public static String normalizeCatalogType(String type) {
+ if (type == null) {
+ return null;
+ }
+ if (CatalogMetaProperties.CATALOG_TYPE_FILESYSTEM.equalsIgnoreCase(type)) {
+ return CatalogMetaProperties.CATALOG_TYPE_HADOOP;
+ }
+ return type;
+ }
+
private static boolean propertyAsBoolean(
Map<String, String> properties, String property, boolean defaultValue) {
String value = properties.get(property);
diff --git
a/amoro-format-hudi/src/main/java/org/apache/amoro/formats/hudi/HudiCatalogFactory.java
b/amoro-format-hudi/src/main/java/org/apache/amoro/formats/hudi/HudiCatalogFactory.java
index 86537594a..d50cfcdcd 100644
---
a/amoro-format-hudi/src/main/java/org/apache/amoro/formats/hudi/HudiCatalogFactory.java
+++
b/amoro-format-hudi/src/main/java/org/apache/amoro/formats/hudi/HudiCatalogFactory.java
@@ -34,7 +34,8 @@ public class HudiCatalogFactory implements
FormatCatalogFactory {
String metastoreType,
Map<String, String> properties,
TableMetaStore metaStore) {
- if
(CatalogMetaProperties.CATALOG_TYPE_HADOOP.equalsIgnoreCase(metastoreType)) {
+ if
(CatalogMetaProperties.CATALOG_TYPE_HADOOP.equalsIgnoreCase(metastoreType)
+ ||
CatalogMetaProperties.CATALOG_TYPE_FILESYSTEM.equalsIgnoreCase(metastoreType)) {
return new HudiHadoopCatalog(catalogName, properties, metaStore);
} else if
(CatalogMetaProperties.CATALOG_TYPE_HIVE.equalsIgnoreCase(metastoreType)) {
return new HudiHiveCatalog(catalogName, properties, metaStore);
diff --git
a/amoro-format-iceberg/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
b/amoro-format-iceberg/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
index 90fea3e7e..4135a52ce 100644
---
a/amoro-format-iceberg/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
+++
b/amoro-format-iceberg/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
@@ -28,6 +28,7 @@ import org.apache.amoro.mixed.MixedFormatCatalog;
import org.apache.amoro.properties.CatalogMetaProperties;
import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
import org.apache.amoro.table.TableMetaStore;
+import org.apache.amoro.utils.CatalogUtil;
import java.util.Map;
@@ -52,7 +53,7 @@ public class MixedIcebergCatalogFactory implements
FormatCatalogFactory {
public Map<String, String> convertCatalogProperties(
String catalogName, String metastoreType, Map<String, String>
unifiedCatalogProperties) {
Map<String, String> properties = Maps.newHashMap(unifiedCatalogProperties);
- properties.put(ICEBERG_CATALOG_TYPE, metastoreType);
+ properties.put(ICEBERG_CATALOG_TYPE,
CatalogUtil.normalizeCatalogType(metastoreType));
properties.put(CatalogMetaProperties.TABLE_FORMATS, format().name());
return properties;
}
diff --git
a/amoro-format-iceberg/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
b/amoro-format-iceberg/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
index 277edfc3a..339608d26 100644
---
a/amoro-format-iceberg/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
+++
b/amoro-format-iceberg/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
@@ -82,6 +82,7 @@ public class CatalogLoader {
String catalogImpl;
switch (metastoreType) {
case CatalogMetaProperties.CATALOG_TYPE_HADOOP:
+ case CatalogMetaProperties.CATALOG_TYPE_FILESYSTEM:
case CatalogMetaProperties.CATALOG_TYPE_GLUE:
case CatalogMetaProperties.CATALOG_TYPE_REST:
case CatalogMetaProperties.CATALOG_TYPE_CUSTOM:
@@ -168,7 +169,7 @@ public class CatalogLoader {
String catalogImpl = catalogImpl(metastoreType, properties);
MixedFormatCatalog catalog = buildCatalog(catalogImpl);
if (!properties.containsKey(ICEBERG_CATALOG_TYPE)) {
- properties.put(ICEBERG_CATALOG_TYPE, metastoreType);
+ properties.put(ICEBERG_CATALOG_TYPE,
CatalogUtil.normalizeCatalogType(metastoreType));
}
catalog.initialize(catalogName, properties, metaStore);
return catalog;
diff --git
a/amoro-format-iceberg/src/main/java/org/apache/amoro/utils/MixedFormatCatalogUtil.java
b/amoro-format-iceberg/src/main/java/org/apache/amoro/utils/MixedFormatCatalogUtil.java
index c612b7bc2..71b060349 100644
---
a/amoro-format-iceberg/src/main/java/org/apache/amoro/utils/MixedFormatCatalogUtil.java
+++
b/amoro-format-iceberg/src/main/java/org/apache/amoro/utils/MixedFormatCatalogUtil.java
@@ -80,7 +80,8 @@ public class MixedFormatCatalogUtil {
String catalogName, String metastoreType, Map<String, String>
properties) {
Map<String, String> icebergCatalogProperties = Maps.newHashMap(properties);
icebergCatalogProperties.put(
- org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE, metastoreType);
+ org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE,
+ CatalogUtil.normalizeCatalogType(metastoreType));
if (CatalogMetaProperties.CATALOG_TYPE_GLUE.equals(metastoreType)) {
icebergCatalogProperties.put(CatalogProperties.CATALOG_IMPL,
GlueCatalog.class.getName());
}
diff --git a/amoro-web/src/services/setting.services.ts
b/amoro-web/src/services/setting.services.ts
index e7ce6652d..6098e1303 100644
--- a/amoro-web/src/services/setting.services.ts
+++ b/amoro-web/src/services/setting.services.ts
@@ -22,6 +22,12 @@ import request from '@/utils/request'
export function getCatalogsTypes() {
return request.get('api/ams/v1/catalogs/metastore/types')
}
+export function getMetastoreTableFormats(type: string) {
+ return request.get(`api/ams/v1/catalogs/metastore/${type}/table-formats`)
+}
+export function getMetastoreStorageTypes(type: string) {
+ return request.get(`api/ams/v1/catalogs/metastore/${type}/storage-types`)
+}
export function getCatalogsSetting(catalogName: string) {
return request.get(`api/ams/v1/catalogs/${catalogName}`)
}
diff --git a/amoro-web/src/views/catalogs/Detail.vue
b/amoro-web/src/views/catalogs/Detail.vue
index 37073257e..12a523658 100644
--- a/amoro-web/src/views/catalogs/Detail.vue
+++ b/amoro-web/src/views/catalogs/Detail.vue
@@ -29,7 +29,7 @@ import {
message,
} from 'ant-design-vue'
import Properties from './Properties.vue'
-import { checkCatalogStatus, delCatalog, getCatalogsSetting, getCatalogsTypes,
saveCatalogsSetting } from '@/services/setting.services'
+import { checkCatalogStatus, delCatalog, getCatalogsSetting, getCatalogsTypes,
getMetastoreStorageTypes, getMetastoreTableFormats, saveCatalogsSetting } from
'@/services/setting.services'
import type { ICatalogItem, IIOptimizeGroupItem, ILableAndValue, IMap } from
'@/types/common.type'
import { usePlaceholder } from '@/hooks/usePlaceholder'
import { getResourceGroupsListAPI } from '@/services/optimize.service'
@@ -65,13 +65,10 @@ const emit = defineEmits<{
(e: 'updateCatalogs'): void
}>()
-const typeShowMap = { 'Internal Catalog': 'Internal Catalog', 'External
Catalog': 'External Catalog' }
-
const formState: FormState = reactive({
catalog: {
name: '',
type: 'ams',
- typeshow: typeShowMap['Internal Catalog'],
optimizerGroup: undefined,
},
tableFormatList: [],
@@ -129,14 +126,6 @@ const tableFormatText = {
[tableFormatMap.PAIMON]: 'Paimon',
[tableFormatMap.HUDI]: 'Hudi',
}
-const storeSupportFormat: { [prop: string]: string[] } = {
- ams: [tableFormatMap.MIXED_ICEBERG, tableFormatMap.ICEBERG],
- hive: [tableFormatMap.MIXED_HIVE, tableFormatMap.MIXED_ICEBERG,
tableFormatMap.ICEBERG, tableFormatMap.PAIMON, tableFormatMap.HUDI],
- hadoop: [tableFormatMap.MIXED_ICEBERG, tableFormatMap.ICEBERG,
tableFormatMap.PAIMON],
- glue: [tableFormatMap.MIXED_ICEBERG, tableFormatMap.ICEBERG],
- rest: [tableFormatMap.MIXED_ICEBERG, tableFormatMap.ICEBERG],
- custom: [tableFormatMap.MIXED_ICEBERG, tableFormatMap.ICEBERG],
-}
const storageConfigFileNameMap = {
'hadoop.core.site': 'core-site.xml',
@@ -153,10 +142,6 @@ const newCatalogConfig = {
'auth.kerberos.krb5': '',
},
}
-const typwShowOptions = ref([
- { label: typeShowMap['Internal Catalog'], value: typeShowMap['Internal
Catalog'] },
- { label: typeShowMap['External Catalog'], value: typeShowMap['External
Catalog'] },
-])
const hadoopConfigTypeOps = reactive<ILableAndValue[]>([{
label: 'SIMPLE',
@@ -195,6 +180,7 @@ const authConfigMap = {
const defaultPropertiesMap = {
ams: ['warehouse'],
hadoop: ['warehouse'],
+ filesystem: ['warehouse'],
custom: ['catalog-impl'],
glue: ['warehouse', 'lock-impl', 'lock.table'],
rest: ['uri'],
@@ -208,6 +194,8 @@ watch(() => route.query, (value) => {
deep: true,
})
const catalogTypeOps = reactive<ILableAndValue[]>([])
+const storageTypeOptions = ref<ILableAndValue[]>([])
+const tableFormatOptions = ref<string[]>([])
const optimizerGroupList = ref<ILableAndValue[]>([])
function initData() {
getConfigInfo()
@@ -237,19 +225,40 @@ async function getOptimizerGroupList() {
}
async function getCatalogTypeOps() {
const res = await getCatalogsTypes();
- (res || []).forEach((ele: any) => {
- if (ele.value !== 'ams') {
- catalogTypeOps.push({
- label: ele.display,
- value: ele.value,
- })
- }
+ catalogTypeOps.length = 0
+ ;(res || []).forEach((ele: any) => {
+ catalogTypeOps.push({
+ label: ele.display,
+ value: ele.value,
+ })
})
getMetastoreType()
}
function getMetastoreType() {
metastoreType.value = (catalogTypeOps.find(ele => ele.value ===
formState.catalog.type) || {}).label || ''
}
+async function loadMetastoreCapabilities(loadTableFormats: boolean) {
+ const type = formState.catalog.type as string
+ if (!type) {
+ return
+ }
+ const formats = await getMetastoreTableFormats(type)
+ const options = (formats || []) as string[]
+ tableFormatOptions.value = options
+ if (loadTableFormats) {
+ formState.tableFormatList = [...options]
+ }
+ const storageTypes = await getMetastoreStorageTypes(type)
+ storageTypeOptions.value = (storageTypes || []).map((val: string) => ({
+ label: val,
+ value: val,
+ }))
+ const availableTypes = storageTypeOptions.value.map(option => option.value)
+ const currentStorageType = formState.storageConfig['storage.type']
+ if (!currentStorageType || !availableTypes.includes(currentStorageType)) {
+ formState.storageConfig['storage.type'] = availableTypes.length > 0 ?
availableTypes[0] : ''
+ }
+}
async function getConfigInfo() {
try {
loading.value = true
@@ -261,7 +270,7 @@ async function getConfigInfo() {
formState.catalog.name = ''
formState.catalog.type = (type || 'ams') as string
formState.catalog.optimizerGroup = undefined
- formState.tableFormatList = [tableFormatMap.MIXED_ICEBERG]
+ formState.tableFormatList = []
formState.authConfig = { ...newCatalogConfig.authConfig }
formState.storageConfig = { ...newCatalogConfig.storageConfig }
const keys = defaultPropertiesMap[formState.catalog.type as keyof typeof
defaultPropertiesMap] || []
@@ -272,6 +281,7 @@ async function getConfigInfo() {
formState.tableProperties = {}
formState.storageConfigArray.length = 0
formState.authConfigArray.length = 0
+ await changeMetastore()
}
else {
const res = await getCatalogsSetting(catalogname as string)
@@ -290,8 +300,8 @@ async function getConfigInfo() {
formState.storageConfigArray.length = 0
formState.authConfigArray.length = 0
getMetastoreType()
+ await loadMetastoreCapabilities(false)
}
- formState.catalog.typeshow = formState.catalog.type === 'ams' ?
typeShowMap['Internal Catalog'] : typeShowMap['External Catalog']
const { storageConfig, authConfig } = formState
Object.keys(storageConfig).forEach((key) => {
@@ -338,20 +348,7 @@ async function getConfigInfo() {
}
}
-function changeTypeShow(val: string) {
- if (val === typeShowMap['Internal Catalog']) {
- formState.catalog.type = 'ams'
- }
- else {
- formState.catalog.type = catalogTypeOps[0].value
- }
- changeMetastore()
-}
-const formatOptions = computed(() => {
- const type = formState.catalog.type
- return storeSupportFormat[type as keyof typeof storeSupportFormat] || []
-})
async function changeProperties() {
const properties = await
propertiesRef.value.getPropertiesWithoputValidation()
@@ -377,53 +374,6 @@ async function changeProperties() {
formState.properties = properties
}
-const storageConfigTypeS3Oss = reactive<ILableAndValue[]>([{
- label: 'S3',
- value: 'S3',
-}, {
- label: 'OSS',
- value: 'OSS',
-}])
-
-const storageConfigTypeOSS = reactive<ILableAndValue[]>([{
- label: 'OSS',
- value: 'OSS',
-}])
-
-const storageConfigTypeHadoop = reactive<ILableAndValue[]>([{
- label: 'Hadoop',
- value: 'Hadoop',
-}])
-
-const storageConfigTypeHadoopS3Oss = reactive<ILableAndValue[]>([{
- label: 'Hadoop',
- value: 'Hadoop',
-}, {
- label: 'S3',
- value: 'S3',
-}, {
- label: 'OSS',
- value: 'OSS',
-}])
-
-const storageConfigTypeOps = computed(() => {
- const type = formState.catalog.type
- if (type === 'ams' || type === 'custom' || type === 'rest') {
- return storageConfigTypeHadoopS3Oss
- }
- else if (type === 'glue') {
- return storageConfigTypeS3Oss
- }
- else if (type === 'hive') {
- return storageConfigTypeHadoop
- }
- else if (type === 'hadoop') {
- return storageConfigTypeHadoopS3Oss
- }
- else {
- return null
- }
-})
const authTypeOptions = computed(() => {
const type = formState.storageConfig['storage.type']
@@ -440,10 +390,28 @@ const authTypeOptions = computed(() => {
return null
})
+const isAuthDisabled = computed(() => formState.storageConfig['storage.type']
=== 'Local')
+
+watch(
+ () => formState.storageConfig['storage.type'],
+ (storageType) => {
+ if (storageType === 'Local') {
+ if (isNewCatalog.value) {
+ formState.tableFormatList = [tableFormatMap.ICEBERG]
+ }
+ if (!formState.authConfig['auth.type']) {
+ formState.authConfig['auth.type'] = 'SIMPLE'
+ }
+ const simpleUsernameKey = 'auth.simple.hadoop_username'
+ if (!formState.authConfig[simpleUsernameKey]) {
+ formState.authConfig[simpleUsernameKey] = 'local'
+ }
+ }
+ }
+)
+
async function changeMetastore() {
- formState.tableFormatList = [formatOptions.value[0]]
- if (!isNewCatalog.value)
- return
+ await loadMetastoreCapabilities(isNewCatalog.value)
const index = formState.storageConfigArray.findIndex(item => item.key ===
'hive.site')
if (isHiveMetastore.value) {
@@ -472,9 +440,6 @@ async function changeMetastore() {
await changeProperties()
}
-async function changeTableFormat() {
- await changeProperties()
-}
function handleEdit() {
emit('updateEdit', true)
@@ -531,7 +496,7 @@ function handleSave() {
return
}
loading.value = true
- const { typeshow, ...catalogParams } = catalog
+ const catalogParams = catalog
getFileIdParams()
await saveCatalogsSetting({
isCreate: isNewCatalog.value,
@@ -635,37 +600,35 @@ onMounted(() => {
<a-input v-if="isEdit && isNewCatalog"
v-model:value="formState.catalog.name" />
<span v-else class="config-value">{{ formState.catalog.name
}}</span>
</a-form-item>
- <a-form-item :label="$t('type')" :name="['catalog', 'typeshow']">
- <a-select
- v-if="isEdit && isNewCatalog"
v-model:value="formState.catalog.typeshow"
- :options="typwShowOptions" :placeholder="placeholder.selectPh"
@change="changeTypeShow"
- />
- <span v-else>{{ formState.catalog.typeshow }}</span>
- </a-form-item>
<a-form-item
- v-if="formState.catalog.typeshow === typeShowMap['External
Catalog']" :label="$t('metastore')"
+ :label="$t('metastore')"
:name="['catalog', 'type']" :rules="[{ required: isEdit &&
isNewCatalog }]"
>
- <a-select
- v-if="isEdit && isNewCatalog"
v-model:value="formState.catalog.type" :options="catalogTypeOps"
- :placeholder="placeholder.selectPh" @change="changeMetastore"
- />
- <span v-else>{{ metastoreType }}</span>
- </a-form-item>
- <a-form-item
+ <a-select
+ v-if="isEdit && isNewCatalog"
v-model:value="formState.catalog.type" :options="catalogTypeOps"
+ :placeholder="placeholder.selectPh" @change="changeMetastore"
+ />
+ <span v-else>{{ metastoreType }}</span>
+ </a-form-item>
+ <a-form-item
:label="$t('tableFormat')" :name="['tableFormatList']"
- :rules="[{ required: isEdit && isNewCatalog }]"
- >
+ >
<a-checkbox-group
- v-model:value="formState.tableFormatList" :disabled="!isEdit ||
!isNewCatalog"
- @change="changeTableFormat"
+ v-if="isEdit"
+ v-model:value="formState.tableFormatList"
>
- <a-checkbox v-for="item in formatOptions" :key="item"
:value="item">
- {{ tableFormatText[item]
- }}
+ <a-checkbox
+ v-for="item in tableFormatOptions"
+ :key="item"
+ :value="item"
+ >
+ {{ tableFormatText[item] || item }}
</a-checkbox>
</a-checkbox-group>
- </a-form-item>
+ <span v-else class="config-value">
+ {{ formState.tableFormatList.map((item) => tableFormatText[item]
|| item).join(', ') }}
+ </span>
+ </a-form-item>
<a-form-item
:label="$t('optimizerGroup')" :name="['catalog', 'optimizerGroup']"
:rules="[{ required: isEdit }]"
@@ -684,7 +647,7 @@ onMounted(() => {
<a-form-item label="Type" :name="['storageConfig', 'storage.type']"
:rules="[{ required: isEdit }]">
<a-select
v-if="isEdit"
v-model:value="formState.storageConfig['storage.type']"
- :placeholder="placeholder.selectPh"
:options="storageConfigTypeOps"
+ :placeholder="placeholder.selectPh" :options="storageTypeOptions"
/>
<span v-else class="config-value">{{
formState.storageConfig['storage.type'] }}</span>
</a-form-item>
@@ -737,25 +700,25 @@ onMounted(() => {
{{ $t('authenticationConfig') }}
</p>
</a-form-item>
- <a-form-item label="Type" :name="['authConfig', 'auth.type']"
:rules="[{ required: isEdit }]">
+ <a-form-item label="Type" :name="['authConfig', 'auth.type']"
:rules="[{ required: isEdit && !isAuthDisabled }]">
<a-select
v-if="isEdit" v-model:value="formState.authConfig['auth.type']"
- :placeholder="placeholder.selectPh" :options="authTypeOptions"
+ :placeholder="placeholder.selectPh" :options="authTypeOptions"
:disabled="isAuthDisabled"
/>
<span v-else class="config-value">{{
formState.authConfig['auth.type'] }}</span>
</a-form-item>
<a-form-item
v-if="formState.authConfig['auth.type'] === 'SIMPLE'"
label="Hadoop Username"
- :name="['authConfig', 'auth.simple.hadoop_username']" :rules="[{
required: isEdit }]"
+ :name="['authConfig', 'auth.simple.hadoop_username']" :rules="[{
required: isEdit && !isAuthDisabled }]"
>
- <a-input v-if="isEdit"
v-model:value="formState.authConfig['auth.simple.hadoop_username']" />
+ <a-input v-if="isEdit"
v-model:value="formState.authConfig['auth.simple.hadoop_username']"
:disabled="isAuthDisabled" />
<span v-else class="config-value">{{
formState.authConfig['auth.simple.hadoop_username'] }}</span>
</a-form-item>
<a-form-item
v-if="formState.authConfig['auth.type'] === 'KERBEROS'"
label="Kerberos Principal"
- :name="['authConfig', 'auth.kerberos.principal']" :rules="[{
required: isEdit }]"
+ :name="['authConfig', 'auth.kerberos.principal']" :rules="[{
required: isEdit && !isAuthDisabled }]"
>
- <a-input v-if="isEdit"
v-model:value="formState.authConfig['auth.kerberos.principal']" />
+ <a-input v-if="isEdit"
v-model:value="formState.authConfig['auth.kerberos.principal']"
:disabled="isAuthDisabled" />
<span v-else class="config-value">{{
formState.authConfig['auth.kerberos.principal'] }}</span>
</a-form-item>
<div v-if="formState.authConfig['auth.type'] === 'KERBEROS'">
@@ -784,16 +747,16 @@ onMounted(() => {
</div>
<a-form-item
v-if="formState.authConfig['auth.type'] === 'AK/SK'" label="Access
Key"
- :name="['authConfig', 'auth.ak_sk.access_key']" :rules="[{
required: isEdit }]"
+ :name="['authConfig', 'auth.ak_sk.access_key']" :rules="[{
required: isEdit && !isAuthDisabled }]"
>
- <a-input v-if="isEdit"
v-model:value="formState.authConfig['auth.ak_sk.access_key']" />
+ <a-input v-if="isEdit"
v-model:value="formState.authConfig['auth.ak_sk.access_key']"
:disabled="isAuthDisabled" />
<span v-else class="config-value">{{
formState.authConfig['auth.ak_sk.access_key'] }}</span>
</a-form-item>
<a-form-item
v-if="formState.authConfig['auth.type'] === 'AK/SK'" label="Secret
Key"
- :name="['authConfig', 'auth.ak_sk.secret_key']" :rules="[{
required: isEdit }]"
+ :name="['authConfig', 'auth.ak_sk.secret_key']" :rules="[{
required: isEdit && !isAuthDisabled }]"
>
- <a-input v-if="isEdit"
v-model:value="formState.authConfig['auth.ak_sk.secret_key']" />
+ <a-input v-if="isEdit"
v-model:value="formState.authConfig['auth.ak_sk.secret_key']"
:disabled="isAuthDisabled" />
<span v-else class="config-value">{{
formState.authConfig['auth.ak_sk.secret_key'] }}</span>
</a-form-item>
<a-form-item>
diff --git a/amoro-web/src/views/tables/components/TableExplorer.vue
b/amoro-web/src/views/tables/components/TableExplorer.vue
index 0e36851cc..fb6d5b68e 100755
--- a/amoro-web/src/views/tables/components/TableExplorer.vue
+++ b/amoro-web/src/views/tables/components/TableExplorer.vue
@@ -182,7 +182,7 @@ async function loadChildren(node: any) {
const tables = (res || []) as TableItem[]
state.tablesByCatalogDb[cacheKey] = tables
if (!tables.length) {
- data.isLeaf = true
+ data.isLeaf = false
updateTreeNodeChildren(data.key as string, [])
return
}
diff --git a/amoro-web/src/views/tables/index.vue
b/amoro-web/src/views/tables/index.vue
index e1f1cbe9a..8fdd485f1 100644
--- a/amoro-web/src/views/tables/index.vue
+++ b/amoro-web/src/views/tables/index.vue
@@ -164,6 +164,11 @@ export default defineComponent({
const { catalog: oldCatalog, db: oldDb, table: oldTable } = oldVal
if (`${catalog}${db}${table}` !== `${oldCatalog}${oldDb}${oldTable}`) {
state.activeKey = 'Details'
+ nextTick(() => {
+ if (detailRef.value) {
+ detailRef.value.getTableDetails()
+ }
+ })
return
}
state.activeKey = value.tab as string