S3ThriftAdapter.java
// 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.storage;
import org.apache.doris.datasource.property.common.AwsCredentialsProviderMode;
import org.apache.doris.filesystem.properties.S3CompatibleFileSystemProperties;
import org.apache.doris.thrift.TCredProviderType;
import org.apache.doris.thrift.TS3StorageParam;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
/**
* fe-core-only Thrift glue: builds {@link TS3StorageParam} from the persisted user-facing
* {@code s3.*} property map. Behaviourally identical to the legacy
* {@code S3Properties.getS3TStorageParam} (direct code move; the legacy class stays as the
* golden-test oracle until Phase D deletes it).
*
* <p>IMPORTANT: this reads the USER key namespace ({@code s3.endpoint}, {@code s3.access_key},
* ...) — do NOT feed it a backend {@code AWS_*} map.</p>
*/
public final class S3ThriftAdapter {
private static final String ENDPOINT = S3CompatibleFileSystemProperties.PROP_ENDPOINT;
private static final String REGION = S3CompatibleFileSystemProperties.PROP_REGION;
private static final String ACCESS_KEY = S3CompatibleFileSystemProperties.PROP_ACCESS_KEY;
private static final String SECRET_KEY = S3CompatibleFileSystemProperties.PROP_SECRET_KEY;
private static final String SESSION_TOKEN = S3CompatibleFileSystemProperties.PROP_SESSION_TOKEN;
private static final String ROOT_PATH = S3CompatibleFileSystemProperties.PROP_ROOT_PATH;
private static final String BUCKET = S3CompatibleFileSystemProperties.PROP_BUCKET;
private static final String ROLE_ARN = S3CompatibleFileSystemProperties.PROP_ROLE_ARN;
private static final String EXTERNAL_ID = S3CompatibleFileSystemProperties.PROP_EXTERNAL_ID;
private static final String CREDENTIALS_PROVIDER_TYPE =
S3CompatibleFileSystemProperties.PROP_CREDENTIALS_PROVIDER_TYPE;
private static final String ENV_CREDENTIALS_PROVIDER_TYPE = "AWS_CREDENTIALS_PROVIDER_TYPE";
private static final String MAX_CONNECTIONS = S3CompatibleFileSystemProperties.PROP_MAX_CONNECTIONS;
private static final String REQUEST_TIMEOUT_MS = S3CompatibleFileSystemProperties.PROP_REQUEST_TIMEOUT_MS;
private static final String CONNECTION_TIMEOUT_MS = S3CompatibleFileSystemProperties.PROP_CONNECTION_TIMEOUT_MS;
private static final String USE_PATH_STYLE = S3CompatibleFileSystemProperties.PROP_USE_PATH_STYLE;
private static final String DEFAULT_MAX_CONNECTIONS =
S3CompatibleFileSystemProperties.DEFAULT_MAX_CONNECTIONS_VALUE;
private static final String DEFAULT_REQUEST_TIMEOUT_MS =
S3CompatibleFileSystemProperties.DEFAULT_REQUEST_TIMEOUT_MS_VALUE;
private static final String DEFAULT_CONNECTION_TIMEOUT_MS =
S3CompatibleFileSystemProperties.DEFAULT_CONNECTION_TIMEOUT_MS_VALUE;
private S3ThriftAdapter() {
}
/** Direct move of legacy {@code S3Properties.getS3TStorageParam}. */
public static TS3StorageParam getS3TStorageParam(Map<String, String> properties) {
TS3StorageParam s3Info = new TS3StorageParam();
if (properties.containsKey(ROLE_ARN)) {
s3Info.setRoleArn(properties.get(ROLE_ARN));
if (properties.containsKey(EXTERNAL_ID)) {
s3Info.setExternalId(properties.get(EXTERNAL_ID));
}
s3Info.setCredProviderType(getTCredProviderType(properties));
}
s3Info.setEndpoint(properties.get(ENDPOINT));
s3Info.setRegion(properties.get(REGION));
s3Info.setAk(properties.get(ACCESS_KEY));
s3Info.setSk(properties.get(SECRET_KEY));
s3Info.setToken(properties.get(SESSION_TOKEN));
s3Info.setRootPath(properties.get(ROOT_PATH));
s3Info.setBucket(properties.get(BUCKET));
String maxConnections = properties.get(MAX_CONNECTIONS);
s3Info.setMaxConn(Integer.parseInt(maxConnections == null
? DEFAULT_MAX_CONNECTIONS : maxConnections));
String requestTimeoutMs = properties.get(REQUEST_TIMEOUT_MS);
s3Info.setRequestTimeoutMs(Integer.parseInt(requestTimeoutMs == null
? DEFAULT_REQUEST_TIMEOUT_MS : requestTimeoutMs));
String connTimeoutMs = properties.get(CONNECTION_TIMEOUT_MS);
s3Info.setConnTimeoutMs(Integer.parseInt(connTimeoutMs == null
? DEFAULT_CONNECTION_TIMEOUT_MS : connTimeoutMs));
String usePathStyle = properties.getOrDefault(USE_PATH_STYLE, "false");
s3Info.setUsePathStyle(Boolean.parseBoolean(usePathStyle));
return s3Info;
}
/**
* Legacy S3Properties.getCredentialsProviderMode: the user key wins over the legacy
* {@code AWS_CREDENTIALS_PROVIDER_TYPE} env-style key; INSTANCE_PROFILE is the default in
* the thrift/PB context (assume-role paths).
*/
static AwsCredentialsProviderMode getCredentialsProviderMode(Map<String, String> properties,
AwsCredentialsProviderMode defaultMode) {
String mode = properties.get(CREDENTIALS_PROVIDER_TYPE);
if (StringUtils.isBlank(mode)) {
mode = properties.get(ENV_CREDENTIALS_PROVIDER_TYPE);
}
if (StringUtils.isBlank(mode)) {
return defaultMode;
}
return AwsCredentialsProviderMode.fromString(mode);
}
private static TCredProviderType getTCredProviderType(Map<String, String> properties) {
AwsCredentialsProviderMode mode = getCredentialsProviderMode(properties,
AwsCredentialsProviderMode.INSTANCE_PROFILE);
switch (mode) {
case DEFAULT:
return TCredProviderType.DEFAULT;
case ENV:
return TCredProviderType.ENV;
case SYSTEM_PROPERTIES:
return TCredProviderType.SYSTEM_PROPERTIES;
case WEB_IDENTITY:
return TCredProviderType.WEB_IDENTITY;
case CONTAINER:
return TCredProviderType.CONTAINER;
case INSTANCE_PROFILE:
return TCredProviderType.INSTANCE_PROFILE;
case ANONYMOUS:
return TCredProviderType.ANONYMOUS;
default:
throw new IllegalArgumentException("Unsupported AWS credentials provider mode: " + mode);
}
}
}