This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new f9a46e9afa2 branch-4.0: [feat](catalog)AWS Glue supports S3 access via
IAM AssumeRole. #56311 (#56418)
f9a46e9afa2 is described below
commit f9a46e9afa27a47d3155d7758f562e8fb0c5ccab
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Sep 25 09:39:23 2025 -0700
branch-4.0: [feat](catalog)AWS Glue supports S3 access via IAM AssumeRole.
#56311 (#56418)
Cherry-picked from #56311
Co-authored-by: Calvin Kirs <[email protected]>
---
.../ConfigurationAWSCredentialsProvider.java | 23 ++++++++--
.../amazonaws/glue/catalog/util/AWSGlueConfig.java | 2 +
.../doris/datasource/property/ParamRules.java | 51 ++++++++++++++++++++++
.../metastore/AWSGlueMetaStoreBaseProperties.java | 18 ++++----
.../metastore/HMSGlueMetaStoreProperties.java | 16 +++++--
.../metastore/IcebergGlueMetaStoreProperties.java | 32 +++++++++++---
.../storage/AbstractS3CompatibleProperties.java | 11 ++++-
.../datasource/property/storage/S3Properties.java | 26 +++++------
.../doris/datasource/property/ParamRulesTest.java | 34 ++++++++++++++-
.../AWSGlueMetaStoreBasePropertiesTest.java | 14 +++++-
.../datasource/property/metastore/HMSGlueIT.java | 49 +++++++++++++++++++++
.../metastore/HMSGlueMetaStorePropertiesTest.java | 2 +-
.../property/metastore/IcebergGlueIT.java | 51 ++++++++++++++++++++++
13 files changed, 288 insertions(+), 41 deletions(-)
diff --git
a/fe/fe-core/src/main/java/com/amazonaws/glue/catalog/credentials/ConfigurationAWSCredentialsProvider.java
b/fe/fe-core/src/main/java/com/amazonaws/glue/catalog/credentials/ConfigurationAWSCredentialsProvider.java
index dd9f4803970..49bea54c38e 100644
---
a/fe/fe-core/src/main/java/com/amazonaws/glue/catalog/credentials/ConfigurationAWSCredentialsProvider.java
+++
b/fe/fe-core/src/main/java/com/amazonaws/glue/catalog/credentials/ConfigurationAWSCredentialsProvider.java
@@ -22,6 +22,8 @@ import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.BasicSessionCredentials;
+import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
+import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
import com.amazonaws.glue.catalog.util.AWSGlueConfig;
import com.amazonaws.util.StringUtils;
import org.apache.hadoop.conf.Configuration;
@@ -39,13 +41,28 @@ public class ConfigurationAWSCredentialsProvider implements
AWSCredentialsProvid
String accessKey =
StringUtils.trim(conf.get(AWSGlueConfig.AWS_GLUE_ACCESS_KEY));
String secretKey =
StringUtils.trim(conf.get(AWSGlueConfig.AWS_GLUE_SECRET_KEY));
String sessionToken =
StringUtils.trim(conf.get(AWSGlueConfig.AWS_GLUE_SESSION_TOKEN));
+ String roleArn =
StringUtils.trim(conf.get(AWSGlueConfig.AWS_GLUE_ROLE_ARN));
+ String externalId =
StringUtils.trim(conf.get(AWSGlueConfig.AWS_GLUE_EXTERNAL_ID));
if (!StringUtils.isNullOrEmpty(accessKey) &&
!StringUtils.isNullOrEmpty(secretKey)) {
return (StringUtils.isNullOrEmpty(sessionToken) ? new
BasicAWSCredentials(accessKey,
secretKey) : new BasicSessionCredentials(accessKey,
secretKey, sessionToken));
- } else {
- throw new SdkClientException(
- "Unable to load AWS credentials from hive conf
(aws.glue.access-key and aws.glue.secret-key)");
}
+
+ AWSCredentialsProvider longLivedProvider = new
DefaultAWSCredentialsProviderChain();
+
+ if (!StringUtils.isNullOrEmpty(roleArn)) {
+ STSAssumeRoleSessionCredentialsProvider.Builder builder =
+ new
STSAssumeRoleSessionCredentialsProvider.Builder(roleArn, "local-session")
+
.withLongLivedCredentialsProvider(longLivedProvider);
+
+ if (!StringUtils.isNullOrEmpty(externalId)) {
+ builder.withExternalId(externalId);
+ }
+ STSAssumeRoleSessionCredentialsProvider provider = builder.build();
+ return provider.getCredentials();
+ }
+ throw new SdkClientException("Unable to load AWS credentials from any
provider in the chain");
+
}
@Override
diff --git
a/fe/fe-core/src/main/java/com/amazonaws/glue/catalog/util/AWSGlueConfig.java
b/fe/fe-core/src/main/java/com/amazonaws/glue/catalog/util/AWSGlueConfig.java
index eeef8ab84d6..4296eee0e94 100644
---
a/fe/fe-core/src/main/java/com/amazonaws/glue/catalog/util/AWSGlueConfig.java
+++
b/fe/fe-core/src/main/java/com/amazonaws/glue/catalog/util/AWSGlueConfig.java
@@ -61,4 +61,6 @@ public final class AWSGlueConfig {
public static final String AWS_GLUE_ACCESS_KEY = "aws.glue.access-key";
public static final String AWS_GLUE_SECRET_KEY = "aws.glue.secret-key";
public static final String AWS_GLUE_SESSION_TOKEN =
"aws.glue.session-token";
+ public static final String AWS_GLUE_ROLE_ARN = "aws.glue.role-arn";
+ public static final String AWS_GLUE_EXTERNAL_ID = "aws.glue.external-id";
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/ParamRules.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/ParamRules.java
index 2b821768dde..4cf1564cd40 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/ParamRules.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/ParamRules.java
@@ -168,6 +168,57 @@ public class ParamRules {
return this;
}
+ /**
+ * Require that all values must either all exist or all be null/empty.
+ *
+ * @param values array of values to check
+ * @param errorMessage error message if the requirement is violated
+ * @return this ParamRules instance for chaining
+ */
+ public ParamRules requireTogether(String[] values, String errorMessage) {
+ rules.add(() -> {
+ boolean anyPresent = false;
+ boolean allPresent = true;
+
+ for (String val : values) {
+ if (isPresent(val)) {
+ anyPresent = true;
+ } else {
+ allPresent = false;
+ }
+ }
+
+ if (anyPresent && !allPresent) {
+ throw new IllegalArgumentException(errorMessage);
+ }
+ });
+ return this;
+ }
+
+ /**
+ * Require that at least one value in the array is present (non-null and
not empty).
+ *
+ * @param values array of values to check
+ * @param errorMessage error message if none of the values are present
+ * @return this ParamRules instance for chaining
+ */
+ public ParamRules requireAtLeastOne(String[] values, String errorMessage) {
+ rules.add(() -> {
+ boolean anyPresent = false;
+ for (String val : values) {
+ if (isPresent(val)) {
+ anyPresent = true;
+ break;
+ }
+ }
+ if (!anyPresent) {
+ throw new IllegalArgumentException(errorMessage);
+ }
+ });
+ return this;
+ }
+
+
// --------- Utility Methods ----------
/**
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/AWSGlueMetaStoreBaseProperties.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/AWSGlueMetaStoreBaseProperties.java
index b3d99a98db7..2f98830adc4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/AWSGlueMetaStoreBaseProperties.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/AWSGlueMetaStoreBaseProperties.java
@@ -62,13 +62,11 @@ public class AWSGlueMetaStoreBaseProperties {
protected String glueSessionToken = "";
@ConnectorProperty(names = {"glue.role_arn"},
- description = "The IAM role the AWS Glue.",
- supported = false)
+ description = "The IAM role the AWS Glue.")
protected String glueIAMRole = "";
@ConnectorProperty(names = {"glue.external_id"},
- description = "The external id of the AWS Glue.",
- supported = false)
+ description = "The external id of the AWS Glue.")
protected String glueExternalId = "";
public static AWSGlueMetaStoreBaseProperties of(Map<String, String>
properties) {
@@ -96,12 +94,12 @@ public class AWSGlueMetaStoreBaseProperties {
private ParamRules buildRules() {
- return new ParamRules()
- .require(glueAccessKey,
- "glue.access_key is required")
- .require(glueSecretKey,
- "glue.secret_key is required")
- .require(glueEndpoint, "glue.endpoint is required");
+ return new ParamRules().requireTogether(new String[]{glueAccessKey,
glueSecretKey},
+ "glue.access_key and glue.secret_key must be set together")
+ .requireAtLeastOne(new String[]{glueAccessKey, glueIAMRole},
+ "At least one of glue.access_key or glue.role_arn must
be set")
+ .requireAtLeastOne(new String[]{glueEndpoint, glueRegion},
+ "At least one of glue.endpoint or glue.region must be
set");
}
private void checkAndInit() {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/HMSGlueMetaStoreProperties.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/HMSGlueMetaStoreProperties.java
index 1f31fe44dc2..12967749620 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/HMSGlueMetaStoreProperties.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/HMSGlueMetaStoreProperties.java
@@ -20,6 +20,7 @@ package org.apache.doris.datasource.property.metastore;
import org.apache.doris.datasource.property.ConnectorProperty;
import com.amazonaws.ClientConfiguration;
+import com.amazonaws.glue.catalog.util.AWSGlueConfig;
import org.apache.hadoop.hive.conf.HiveConf;
import java.util.Map;
@@ -73,6 +74,7 @@ public class HMSGlueMetaStoreProperties extends
AbstractHMSProperties {
protected String awsGlueCatalogSeparator = "";
// ========== Constructor ==========
+
/**
* Constructs an instance with the given metastore type and original
properties.
*
@@ -98,9 +100,6 @@ public class HMSGlueMetaStoreProperties extends
AbstractHMSProperties {
hiveConf = new HiveConf();
hiveConf.set(AWS_GLUE_ENDPOINT_KEY, baseProperties.glueEndpoint);
hiveConf.set(AWS_REGION_KEY, baseProperties.glueRegion);
- hiveConf.set(AWS_GLUE_SESSION_TOKEN_KEY,
baseProperties.glueSessionToken);
- hiveConf.set(AWS_GLUE_ACCESS_KEY_KEY, baseProperties.glueAccessKey);
- hiveConf.set(AWS_GLUE_SECRET_KEY_KEY, baseProperties.glueSecretKey);
hiveConf.set(AWS_GLUE_MAX_RETRY_KEY,
String.valueOf(awsGlueMaxErrorRetries));
hiveConf.set(AWS_GLUE_MAX_CONNECTIONS_KEY,
String.valueOf(awsGlueMaxConnections));
hiveConf.set(AWS_GLUE_CONNECTION_TIMEOUT_KEY,
String.valueOf(awsGlueConnectionTimeout));
@@ -109,6 +108,17 @@ public class HMSGlueMetaStoreProperties extends
AbstractHMSProperties {
hiveConf.set(AWS_CATALOG_CREDENTIALS_PROVIDER_FACTORY_CLASS_KEY,
"com.amazonaws.glue.catalog.credentials.ConfigurationAWSCredentialsProviderFactory");
hiveConf.set("hive.metastore.type", "glue");
+ setHiveConfPropertiesIfNotNull(hiveConf,
AWSGlueConfig.AWS_GLUE_ACCESS_KEY, baseProperties.glueAccessKey);
+ setHiveConfPropertiesIfNotNull(hiveConf,
AWSGlueConfig.AWS_GLUE_SECRET_KEY, baseProperties.glueSecretKey);
+ setHiveConfPropertiesIfNotNull(hiveConf,
AWSGlueConfig.AWS_GLUE_SESSION_TOKEN, baseProperties.glueSessionToken);
+ setHiveConfPropertiesIfNotNull(hiveConf,
AWSGlueConfig.AWS_GLUE_ROLE_ARN, baseProperties.glueIAMRole);
+ setHiveConfPropertiesIfNotNull(hiveConf,
AWSGlueConfig.AWS_GLUE_EXTERNAL_ID, baseProperties.glueExternalId);
+ }
+
+ private static void setHiveConfPropertiesIfNotNull(HiveConf hiveConf,
String key, String value) {
+ if (value != null) {
+ hiveConf.set(key, value);
+ }
}
public HMSGlueMetaStoreProperties(Map<String, String> origProps) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/IcebergGlueMetaStoreProperties.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/IcebergGlueMetaStoreProperties.java
index 7952f8d0bae..9738feb5be8 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/IcebergGlueMetaStoreProperties.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/metastore/IcebergGlueMetaStoreProperties.java
@@ -83,11 +83,31 @@ public class IcebergGlueMetaStoreProperties extends
AbstractIcebergProperties {
private void appendGlueProps(Map<String, String> props) {
props.put(AwsProperties.GLUE_CATALOG_ENDPOINT,
glueProperties.glueEndpoint);
- props.put("client.credentials-provider",
-
"com.amazonaws.glue.catalog.credentials.ConfigurationAWSCredentialsProvider2x");
- props.put("client.credentials-provider.glue.access_key",
glueProperties.glueAccessKey);
- props.put("client.credentials-provider.glue.secret_key",
glueProperties.glueSecretKey);
- props.put("aws.catalog.credentials.provider.factory.class",
-
"com.amazonaws.glue.catalog.credentials.ConfigurationAWSCredentialsProviderFactory");
+
+ if (StringUtils.isNotBlank(glueProperties.glueAccessKey) && StringUtils
+ .isNotBlank(glueProperties.glueSecretKey)) {
+ props.put("client.credentials-provider",
+
"com.amazonaws.glue.catalog.credentials.ConfigurationAWSCredentialsProvider2x");
+ props.put("client.credentials-provider.glue.access_key",
glueProperties.glueAccessKey);
+ props.put("client.credentials-provider.glue.secret_key",
glueProperties.glueSecretKey);
+ props.put("aws.catalog.credentials.provider.factory.class",
+
"com.amazonaws.glue.catalog.credentials.ConfigurationAWSCredentialsProviderFactory");
+ if (StringUtils.isNotBlank(glueProperties.glueSessionToken)) {
+ props.put("client.credentials-provider.glue.session_token",
glueProperties.glueSessionToken);
+ }
+ return;
+ }
+ //IAM Assume Role
+ if (StringUtils.isNotBlank(glueProperties.glueIAMRole)) {
+ props.put(AwsProperties.CLIENT_FACTORY,
+ "org.apache.iceberg.aws.AssumeRoleAwsClientFactory");
+ props.put("aws.region", glueProperties.glueRegion);
+
+ props.put(AwsProperties.CLIENT_ASSUME_ROLE_ARN,
glueProperties.glueIAMRole);
+ props.put(AwsProperties.CLIENT_ASSUME_ROLE_REGION,
glueProperties.glueRegion);
+ if (StringUtils.isNotBlank(glueProperties.glueExternalId)) {
+ props.put(AwsProperties.CLIENT_ASSUME_ROLE_EXTERNAL_ID,
glueProperties.glueExternalId);
+ }
+ }
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AbstractS3CompatibleProperties.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AbstractS3CompatibleProperties.java
index d2ae8d4260d..65d42077951 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AbstractS3CompatibleProperties.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AbstractS3CompatibleProperties.java
@@ -266,8 +266,15 @@ public abstract class AbstractS3CompatibleProperties
extends StorageProperties i
hadoopStorageConfig.set("fs.s3a.impl",
"org.apache.hadoop.fs.s3a.S3AFileSystem");
hadoopStorageConfig.set("fs.s3a.endpoint", getEndpoint());
hadoopStorageConfig.set("fs.s3a.endpoint.region", getRegion());
- hadoopStorageConfig.set("fs.s3a.access.key", getAccessKey());
- hadoopStorageConfig.set("fs.s3a.secret.key", getSecretKey());
+ hadoopStorageConfig.set("fs.s3.impl.disable.cache", "true");
+ hadoopStorageConfig.set("fs.s3a.impl.disable.cache", "true");
+ if (StringUtils.isNotBlank(getAccessKey())) {
+ hadoopStorageConfig.set("fs.s3a.access.key", getAccessKey());
+ hadoopStorageConfig.set("fs.s3a.secret.key", getSecretKey());
+ if (StringUtils.isNotBlank(getSessionToken())) {
+ hadoopStorageConfig.set("fs.s3a.session.token",
getSessionToken());
+ }
+ }
hadoopStorageConfig.set("fs.s3a.connection.maximum",
getMaxConnections());
hadoopStorageConfig.set("fs.s3a.connection.request.timeout",
getRequestTimeoutS());
hadoopStorageConfig.set("fs.s3a.connection.timeout",
getConnectionTimeoutS());
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/S3Properties.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/S3Properties.java
index 130240ad53d..c9b922f0d19 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/S3Properties.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/S3Properties.java
@@ -156,12 +156,12 @@ public class S3Properties extends
AbstractS3CompatibleProperties {
description = "The sts region of S3.")
protected String s3StsRegion = "";
- @ConnectorProperty(names = {"s3.role_arn", "AWS_ROLE_ARN"},
+ @ConnectorProperty(names = {"s3.role_arn", "AWS_ROLE_ARN",
"glue.role_arn"},
required = false,
description = "The iam role of S3.")
protected String s3IAMRole = "";
- @ConnectorProperty(names = {"s3.external_id", "AWS_EXTERNAL_ID"},
+ @ConnectorProperty(names = {"s3.external_id", "AWS_EXTERNAL_ID",
"glue.external_id"},
required = false,
description = "The external id of S3.")
protected String s3ExternalId = "";
@@ -345,17 +345,17 @@ public class S3Properties extends
AbstractS3CompatibleProperties {
/**
* ===========================================
- * NOTICE:
- * This parameter is still used for Cloud-related features,
- * although it is no longer recommended.
- *
- * Reason:
- * - Cloud may access S3-compatible object storage via the S3 protocol.
- * - The exact behavior has not yet been fully clarified.
- *
- * Therefore:
- * - We cannot directly replace it with the new parameter.
- * - This redundant parameter is temporarily kept for compatibility.
+ * NOTICE:
+ * This parameter is still used for Cloud-related features,
+ * although it is no longer recommended.
+ * <p>
+ * Reason:
+ * - Cloud may access S3-compatible object storage via the S3 protocol.
+ * - The exact behavior has not yet been fully clarified.
+ * <p>
+ * Therefore:
+ * - We cannot directly replace it with the new parameter.
+ * - This redundant parameter is temporarily kept for compatibility.
* ===========================================
*/
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/ParamRulesTest.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/ParamRulesTest.java
index d47695c5272..afa0614b453 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/ParamRulesTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/ParamRulesTest.java
@@ -17,7 +17,7 @@
package org.apache.doris.datasource.property;
-import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
@@ -115,4 +115,36 @@ public class ParamRulesTest {
() -> rules.validate("Config Error"));
Assertions.assertEquals("Config Error: Missing value", e.getMessage());
}
+
+ @Test
+ void testRequireTogether() {
+ ParamRules rules = new ParamRules()
+ .requireTogether(new String[]{"accessKey", ""}, "Both
accessKey and secretKey are required together");
+ IllegalArgumentException e =
Assertions.assertThrows(IllegalArgumentException.class,
+ () -> rules.validate());
+ Assertions.assertEquals("Both accessKey and secretKey are required
together", e.getMessage());
+ ParamRules rightRule = new ParamRules()
+ .requireTogether(new String[]{"accessKey", "secretKey"}, "Both
accessKey and secretKey are required together");
+ Assertions.assertDoesNotThrow(() -> rightRule.validate());
+ }
+
+ @Test
+ void testAtLeastOne() {
+ ParamRules rules = new ParamRules()
+ .requireAtLeastOne(new String[]{""}, "At least one of
accessKey and iamrole is required");
+ IllegalArgumentException e =
Assertions.assertThrows(IllegalArgumentException.class,
+ () -> rules.validate());
+ Assertions.assertEquals("At least one of accessKey and iamrole is
required", e.getMessage());
+ ParamRules rightRule1 = new ParamRules()
+ .requireAtLeastOne(new String[]{"accessKey", "iamrole"}, "At
least one of accessKey and iamrole is required");
+ Assertions.assertDoesNotThrow(() -> rightRule1.validate());
+ ParamRules rightRule2 = new ParamRules()
+ .requireAtLeastOne(new String[]{"accessKey", ""}, "At least
one of accessKey and iamrole is required");
+ Assertions.assertDoesNotThrow(() -> rightRule2.validate());
+ ParamRules rightRule3 = new ParamRules()
+ .requireAtLeastOne(
+ new String[]{"", "iamrole"}, "At least one of
accessKey and iamrole is required"
+ );
+ Assertions.assertDoesNotThrow(() -> rightRule3.validate());
+ }
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/AWSGlueMetaStoreBasePropertiesTest.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/AWSGlueMetaStoreBasePropertiesTest.java
index 945c862f4b2..bcb04d0da2f 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/AWSGlueMetaStoreBasePropertiesTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/AWSGlueMetaStoreBasePropertiesTest.java
@@ -70,7 +70,7 @@ public class AWSGlueMetaStoreBasePropertiesTest {
IllegalArgumentException.class,
() -> AWSGlueMetaStoreBaseProperties.of(props)
);
- Assertions.assertTrue(ex.getMessage().contains("glue.secret_key is
required"));
+ Assertions.assertTrue(ex.getMessage().contains("glue.access_key and
glue.secret_key must be set together"));
}
@Test
@@ -82,7 +82,7 @@ public class AWSGlueMetaStoreBasePropertiesTest {
IllegalArgumentException.class,
() -> AWSGlueMetaStoreBaseProperties.of(props)
);
- Assertions.assertTrue(ex.getMessage().contains("glue.endpoint is
required"));
+ Assertions.assertTrue(ex.getMessage().contains("At least one of
glue.endpoint or glue.region must be set"));
}
@Test
@@ -108,4 +108,14 @@ public class AWSGlueMetaStoreBasePropertiesTest {
);
Assertions.assertTrue(ex.getMessage().contains("Invalid AWS Glue
endpoint"));
}
+
+ @Test
+ void testIamRole() {
+ Map<String, String> props = baseValidProps();
+ props.remove("glue.access_key");
+ props.remove("glue.secret_key");
+ props.put("glue.role_arn", "arn:aws:iam::1001:role/doris-glue-role");
+ AWSGlueMetaStoreBaseProperties glueProps =
AWSGlueMetaStoreBaseProperties.of(props);
+ Assertions.assertEquals("arn:aws:iam::1001:role/doris-glue-role",
glueProps.glueIAMRole);
+ }
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/HMSGlueIT.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/HMSGlueIT.java
new file mode 100644
index 00000000000..ceec4b94fbe
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/HMSGlueIT.java
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.datasource.property.metastore;
+
+import org.apache.doris.common.UserException;
+import org.apache.doris.common.security.authentication.ExecutionAuthenticator;
+import org.apache.doris.datasource.hive.ThriftHMSCachedClient;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Map;
+
+/*
+ * This is for local development and testing only. Use actual environment
settings in production
+ */
+public class HMSGlueIT {
+
+ public static void main(String[] args) throws UserException {
+ Map<String, String> baseProps = ImmutableMap.of(
+ "type", "hms",
+ "hive.metastore.type", "glue",
+ "glue.role_arn", "arn:aws:iam::1001:role/doris-glue-role",
+ "glue.external_id", "1001",
+ "glue.endpoint", "https://glue.us-east-1.amazonaws.com"
+ );
+ System.setProperty("aws.region", "us-east-1");
+ System.setProperty("aws.accessKeyId", "");
+ System.setProperty("aws.secretKey", "");
+ HMSGlueMetaStoreProperties properties = (HMSGlueMetaStoreProperties)
MetastoreProperties.create(baseProps);
+ ThriftHMSCachedClient client = new
ThriftHMSCachedClient(properties.hiveConf, 1, new ExecutionAuthenticator() {
+ });
+ client.getTable("default", "test_hive_table");
+ }
+}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/HMSGlueMetaStorePropertiesTest.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/HMSGlueMetaStorePropertiesTest.java
index 6ac93e448b6..8ab2ea0642b 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/HMSGlueMetaStorePropertiesTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/HMSGlueMetaStorePropertiesTest.java
@@ -74,7 +74,7 @@ public class HMSGlueMetaStorePropertiesTest {
incompleteConfig.remove("aws.glue.secret-key");
HMSGlueMetaStoreProperties props = new
HMSGlueMetaStoreProperties(incompleteConfig);
Exception exception =
Assertions.assertThrows(IllegalArgumentException.class,
props::initNormalizeAndCheckProps);
- Assertions.assertTrue(exception.getMessage().contains("glue.secret_key
is required"));
+ Assertions.assertTrue(exception.getMessage().contains("glue.access_key
and glue.secret_key must be set together"));
}
@Test
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/IcebergGlueIT.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/IcebergGlueIT.java
new file mode 100644
index 00000000000..c91194eeb8c
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/metastore/IcebergGlueIT.java
@@ -0,0 +1,51 @@
+// 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.doris.datasource.property.metastore;
+
+import org.apache.doris.common.UserException;
+import org.apache.doris.datasource.property.storage.StorageProperties;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.catalog.SupportsNamespaces;
+
+import java.util.List;
+import java.util.Map;
+
+/*
+ * This is for local development and testing only. Use actual environment
settings in production
+ */
+public class IcebergGlueIT {
+ public static void main(String[] args) throws UserException {
+
+ Map<String, String> baseProps = ImmutableMap.of(
+ "type", "iceberg",
+ "iceberg.catalog.type", "glue",
+ "glue.role_arn", "arn:aws:iam::12345:role/kristen",
+ "glue.external_id", "1001",
+ "glue.endpoint", "https://glue.us-east-1.amazonaws.com"
+ );
+ System.setProperty("aws.region", "us-east-1");
+ System.setProperty("aws.accessKeyId", "acc");
+ System.setProperty("aws.secretAccessKey", "heyhey");
+ IcebergGlueMetaStoreProperties properties =
(IcebergGlueMetaStoreProperties) MetastoreProperties.create(baseProps);
+ List<StorageProperties> storagePropertiesList =
StorageProperties.createAll(baseProps);
+ SupportsNamespaces catalog = (SupportsNamespaces)
properties.initializeCatalog("iceberg_glue_test", storagePropertiesList);
+ catalog.listNamespaces().forEach(System.out::println);
+
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]