This is an automated email from the ASF dual-hosted git repository.
snazy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push:
new 355adae1f Make `*StorageConfigurationInfo` types immutable (#2236)
355adae1f is described below
commit 355adae1f6169b91bc78b0fe71ff863ee19798e8
Author: Robert Stupp <[email protected]>
AuthorDate: Tue Aug 5 13:47:40 2025 +0200
Make `*StorageConfigurationInfo` types immutable (#2236)
This change eventually enables usage of the `*StorageConfigurationInfo` in
the `StorageCredentialCacheKey` due to the then memoized hash-code values, to
eliminate a couple of JSON re-serializations.
---
.../apache/polaris/core/entity/CatalogEntity.java | 48 +++---
.../core/storage/FileStorageConfigurationInfo.java | 24 ++-
.../storage/PolarisStorageConfigurationInfo.java | 45 +++---
.../core/storage/StorageConfigurationOverride.java | 18 ++-
.../storage/aws/AwsStorageConfigurationInfo.java | 165 +++++----------------
.../azure/AzureStorageConfigurationInfo.java | 72 +++------
.../storage/gcp/GcpStorageConfigurationInfo.java | 48 +++---
.../storage/InMemoryStorageIntegrationTest.java | 44 +++---
.../aws/AwsStorageConfigurationInfoTest.java | 64 ++++----
.../PolarisStorageConfigurationInfoTest.java | 118 +++++++++++++++
.../aws/AwsCredentialsStorageIntegrationTest.java | 112 +++++++-------
.../AzureCredentialStorageIntegrationTest.java | 9 +-
.../gcp/GcpCredentialsStorageIntegrationTest.java | 10 +-
13 files changed, 395 insertions(+), 382 deletions(-)
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/entity/CatalogEntity.java
b/polaris-core/src/main/java/org/apache/polaris/core/entity/CatalogEntity.java
index ba8627f06..622df1fca 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/entity/CatalogEntity.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/entity/CatalogEntity.java
@@ -22,7 +22,6 @@ import static
org.apache.polaris.core.admin.model.StorageConfigInfo.StorageTypeE
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -269,37 +268,40 @@ public class CatalogEntity extends PolarisEntity
implements LocationBasedEntity
case S3:
AwsStorageConfigInfo awsConfigModel = (AwsStorageConfigInfo)
storageConfigModel;
AwsStorageConfigurationInfo awsConfig =
- new AwsStorageConfigurationInfo(
- PolarisStorageConfigurationInfo.StorageType.S3,
- new ArrayList<>(allowedLocations),
- awsConfigModel.getRoleArn(),
- awsConfigModel.getExternalId(),
- awsConfigModel.getRegion(),
- awsConfigModel.getEndpoint(),
- awsConfigModel.getStsEndpoint(),
- awsConfigModel.getPathStyleAccess(),
- awsConfigModel.getEndpointInternal());
+ AwsStorageConfigurationInfo.builder()
+ .allowedLocations(allowedLocations)
+ .roleARN(awsConfigModel.getRoleArn())
+ .externalId(awsConfigModel.getExternalId())
+ .region(awsConfigModel.getRegion())
+ .endpoint(awsConfigModel.getEndpoint())
+ .stsEndpoint(awsConfigModel.getStsEndpoint())
+ .pathStyleAccess(awsConfigModel.getPathStyleAccess())
+ .endpointInternal(awsConfigModel.getEndpointInternal())
+ .build();
awsConfig.validateArn(awsConfigModel.getRoleArn());
config = awsConfig;
break;
case AZURE:
AzureStorageConfigInfo azureConfigModel = (AzureStorageConfigInfo)
storageConfigModel;
- AzureStorageConfigurationInfo azureConfigInfo =
- new AzureStorageConfigurationInfo(
- new ArrayList<>(allowedLocations),
azureConfigModel.getTenantId());
-
azureConfigInfo.setMultiTenantAppName(azureConfigModel.getMultiTenantAppName());
- azureConfigInfo.setConsentUrl(azureConfigModel.getConsentUrl());
- config = azureConfigInfo;
+ config =
+ AzureStorageConfigurationInfo.builder()
+ .allowedLocations(allowedLocations)
+ .tenantId(azureConfigModel.getTenantId())
+
.multiTenantAppName(azureConfigModel.getMultiTenantAppName())
+ .consentUrl(azureConfigModel.getConsentUrl())
+ .build();
break;
case GCS:
- GcpStorageConfigurationInfo gcpConfig =
- new GcpStorageConfigurationInfo(new
ArrayList<>(allowedLocations));
- gcpConfig.setGcpServiceAccount(
- ((GcpStorageConfigInfo)
storageConfigModel).getGcsServiceAccount());
- config = gcpConfig;
+ config =
+ GcpStorageConfigurationInfo.builder()
+ .allowedLocations(allowedLocations)
+ .gcpServiceAccount(
+ ((GcpStorageConfigInfo)
storageConfigModel).getGcsServiceAccount())
+ .build();
break;
case FILE:
- config = new FileStorageConfigurationInfo(new
ArrayList<>(allowedLocations));
+ config =
+
FileStorageConfigurationInfo.builder().allowedLocations(allowedLocations).build();
break;
default:
throw new IllegalStateException(
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/storage/FileStorageConfigurationInfo.java
b/polaris-core/src/main/java/org/apache/polaris/core/storage/FileStorageConfigurationInfo.java
index 6b1d48c5c..6b4fe51f7 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/storage/FileStorageConfigurationInfo.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/storage/FileStorageConfigurationInfo.java
@@ -18,22 +18,25 @@
*/
package org.apache.polaris.core.storage;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import jakarta.annotation.Nonnull;
-import java.util.List;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.Locale;
+import org.apache.polaris.immutables.PolarisImmutable;
/**
* Support for file:// URLs in storage configuration. This is pretty-much only
used for testing.
* Supports URLs that start with file:// or /, but also supports wildcard (*)
to support certain
* test cases.
*/
-public class FileStorageConfigurationInfo extends
PolarisStorageConfigurationInfo {
+@PolarisImmutable
+@JsonSerialize(as = ImmutableFileStorageConfigurationInfo.class)
+@JsonDeserialize(as = ImmutableFileStorageConfigurationInfo.class)
+@JsonTypeName("FileStorageConfigurationInfo")
+public abstract class FileStorageConfigurationInfo extends
PolarisStorageConfigurationInfo {
- public FileStorageConfigurationInfo(
- @JsonProperty(value = "allowedLocations", required = true) @Nonnull
- List<String> allowedLocations) {
- super(StorageType.FILE, allowedLocations);
+ public static ImmutableFileStorageConfigurationInfo.Builder builder() {
+ return ImmutableFileStorageConfigurationInfo.builder();
}
@Override
@@ -41,6 +44,11 @@ public class FileStorageConfigurationInfo extends
PolarisStorageConfigurationInf
return "org.apache.iceberg.hadoop.HadoopFileIO";
}
+ @Override
+ public StorageType getStorageType() {
+ return StorageType.FILE;
+ }
+
@Override
public void validatePrefixForStorageType(String loc) {
if (getStorageType().getPrefixes().stream()
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisStorageConfigurationInfo.java
b/polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisStorageConfigurationInfo.java
index d039b1f61..414156fb4 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisStorageConfigurationInfo.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisStorageConfigurationInfo.java
@@ -18,8 +18,9 @@
*/
package org.apache.polaris.core.storage;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -46,6 +47,7 @@ import
org.apache.polaris.core.entity.table.IcebergTableLikeEntity;
import org.apache.polaris.core.storage.aws.AwsStorageConfigurationInfo;
import org.apache.polaris.core.storage.azure.AzureStorageConfigurationInfo;
import org.apache.polaris.core.storage.gcp.GcpStorageConfigurationInfo;
+import org.immutables.value.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,40 +67,28 @@ import org.slf4j.LoggerFactory;
@JsonSubTypes.Type(value = GcpStorageConfigurationInfo.class),
@JsonSubTypes.Type(value = FileStorageConfigurationInfo.class),
})
+@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class PolarisStorageConfigurationInfo {
private static final Logger LOGGER =
LoggerFactory.getLogger(PolarisStorageConfigurationInfo.class);
- // a list of allowed locations
- private final List<String> allowedLocations;
-
- // storage type
- private final StorageType storageType;
-
- public PolarisStorageConfigurationInfo(
- @JsonProperty(value = "storageType", required = true) @Nonnull
StorageType storageType,
- @JsonProperty(value = "allowedLocations", required = true) @Nonnull
- List<String> allowedLocations) {
- this(storageType, allowedLocations, true);
- }
-
- protected PolarisStorageConfigurationInfo(
- StorageType storageType, List<String> allowedLocations, boolean
validatePrefix) {
- this.allowedLocations = allowedLocations;
- this.storageType = storageType;
- if (validatePrefix) {
- allowedLocations.forEach(this::validatePrefixForStorageType);
+ @Value.Check
+ protected void check() {
+ if (validatePrefix()) {
+ getAllowedLocations().forEach(this::validatePrefixForStorageType);
}
}
- public List<String> getAllowedLocations() {
- return allowedLocations;
+ @JsonIgnore
+ @Value.Auxiliary
+ public boolean validatePrefix() {
+ return true;
}
- public StorageType getStorageType() {
- return storageType;
- }
+ public abstract List<String> getAllowedLocations();
+
+ public abstract StorageType getStorageType();
private static final ObjectMapper DEFAULT_MAPPER;
@@ -213,11 +203,12 @@ public abstract class PolarisStorageConfigurationInfo {
/** Validate if the provided allowed locations are valid for the storage
type */
protected void validatePrefixForStorageType(String loc) {
- if (storageType.prefixes.stream().noneMatch(p ->
loc.toLowerCase(Locale.ROOT).startsWith(p))) {
+ if (getStorageType().prefixes.stream()
+ .noneMatch(p -> loc.toLowerCase(Locale.ROOT).startsWith(p))) {
throw new IllegalArgumentException(
String.format(
"Location prefix not allowed: '%s', expected prefixes: '%s'",
- loc, String.join(",", storageType.prefixes)));
+ loc, String.join(",", getStorageType().prefixes)));
}
}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/storage/StorageConfigurationOverride.java
b/polaris-core/src/main/java/org/apache/polaris/core/storage/StorageConfigurationOverride.java
index 1d695dbb1..b38ebf2fc 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/storage/StorageConfigurationOverride.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/storage/StorageConfigurationOverride.java
@@ -30,20 +30,36 @@ import java.util.List;
public class StorageConfigurationOverride extends
PolarisStorageConfigurationInfo {
private final PolarisStorageConfigurationInfo parentStorageConfiguration;
+ private final List<String> allowedLocations;
public StorageConfigurationOverride(
@Nonnull PolarisStorageConfigurationInfo parentStorageConfiguration,
List<String> allowedLocations) {
- super(parentStorageConfiguration.getStorageType(), allowedLocations,
false);
this.parentStorageConfiguration = parentStorageConfiguration;
+ this.allowedLocations = List.copyOf(allowedLocations);
allowedLocations.forEach(this::validatePrefixForStorageType);
}
+ @Override
+ public List<String> getAllowedLocations() {
+ return allowedLocations;
+ }
+
+ @Override
+ public StorageType getStorageType() {
+ return parentStorageConfiguration.getStorageType();
+ }
+
@Override
public String getFileIoImplClassName() {
return parentStorageConfiguration.getFileIoImplClassName();
}
+ @Override
+ public boolean validatePrefix() {
+ return false;
+ }
+
// delegate to the wrapped class in case they override the parent behavior
@Override
protected void validatePrefixForStorageType(String loc) {
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java
b/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java
index bd325d103..4181d205e 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfo.java
@@ -18,20 +18,27 @@
*/
package org.apache.polaris.core.storage.aws;
-import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.MoreObjects;
-import jakarta.annotation.Nonnull;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import jakarta.annotation.Nullable;
import java.net.URI;
-import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.polaris.core.storage.PolarisStorageConfigurationInfo;
+import org.apache.polaris.immutables.PolarisImmutable;
/** Aws Polaris Storage Configuration information */
-public class AwsStorageConfigurationInfo extends
PolarisStorageConfigurationInfo {
+@PolarisImmutable
+@JsonSerialize(as = ImmutableAwsStorageConfigurationInfo.class)
+@JsonDeserialize(as = ImmutableAwsStorageConfigurationInfo.class)
+@JsonTypeName("AwsStorageConfigurationInfo")
+public abstract class AwsStorageConfigurationInfo extends
PolarisStorageConfigurationInfo {
+
+ public static ImmutableAwsStorageConfigurationInfo.Builder builder() {
+ return ImmutableAwsStorageConfigurationInfo.builder();
+ }
// Technically, it should be
^arn:(aws|aws-cn|aws-us-gov):iam::(\d{12}):role/.+$,
@JsonIgnore
@@ -39,74 +46,9 @@ public class AwsStorageConfigurationInfo extends
PolarisStorageConfigurationInfo
private static final Pattern ROLE_ARN_PATTERN_COMPILED =
Pattern.compile(ROLE_ARN_PATTERN);
- // AWS role to be assumed
- private final @Nonnull String roleARN;
-
- // AWS external ID, optional
- @JsonProperty(value = "externalId")
- private @Nullable String externalId = null;
-
- /** User ARN for the service principal */
- @JsonProperty(value = "userARN")
- private @Nullable String userARN = null;
-
- /** User ARN for the service principal */
- @JsonProperty(value = "region")
- private @Nullable String region = null;
-
- /** Endpoint URI for S3 API calls */
- @JsonProperty(value = "endpoint")
- private @Nullable String endpoint;
-
- /** Endpoint URI for internal Polaris calls to S3 API */
- @JsonProperty(value = "endpointInternal")
- private @Nullable String endpointInternal;
-
- /** Endpoint URI for STS API calls */
- @JsonProperty(value = "stsEndpoint")
- private @Nullable String stsEndpoint;
-
- /** A flag indicating whether path-style bucket access should be forced in
S3 clients. */
- @JsonProperty(value = "pathStyleAccess")
- private Boolean pathStyleAccess;
-
- @JsonCreator
- public AwsStorageConfigurationInfo(
- @JsonProperty(value = "storageType", required = true) @Nonnull
StorageType storageType,
- @JsonProperty(value = "allowedLocations", required = true) @Nonnull
- List<String> allowedLocations,
- @JsonProperty(value = "roleARN", required = true) @Nonnull String
roleARN,
- @JsonProperty(value = "externalId") @Nullable String externalId,
- @JsonProperty(value = "region", required = false) @Nullable String
region,
- @JsonProperty(value = "endpoint") @Nullable String endpoint,
- @JsonProperty(value = "stsEndpoint") @Nullable String stsEndpoint,
- @JsonProperty(value = "pathStyleAccess") @Nullable Boolean
pathStyleAccess,
- @JsonProperty(value = "endpointInternal") @Nullable String
endpointInternal) {
- super(storageType, allowedLocations);
- this.roleARN = roleARN;
- this.externalId = externalId;
- this.region = region;
- this.endpoint = endpoint;
- this.stsEndpoint = stsEndpoint;
- this.pathStyleAccess = pathStyleAccess;
- this.endpointInternal = endpointInternal;
- }
-
- public AwsStorageConfigurationInfo(
- @Nonnull StorageType storageType,
- @Nonnull List<String> allowedLocations,
- @Nonnull String roleARN,
- @Nullable String region) {
- this(storageType, allowedLocations, roleARN, null, region, null, null,
null, null);
- }
-
- public AwsStorageConfigurationInfo(
- @Nonnull StorageType storageType,
- @Nonnull List<String> allowedLocations,
- @Nonnull String roleARN,
- @Nullable String externalId,
- @Nullable String region) {
- this(storageType, allowedLocations, roleARN, externalId, region, null,
null, null, null);
+ @Override
+ public StorageType getStorageType() {
+ return StorageType.S3;
}
@Override
@@ -127,76 +69,62 @@ public class AwsStorageConfigurationInfo extends
PolarisStorageConfigurationInfo
}
}
- public @Nonnull String getRoleARN() {
- return roleARN;
- }
-
- public @Nullable String getExternalId() {
- return externalId;
- }
+ public abstract String getRoleARN();
- public void setExternalId(@Nullable String externalId) {
- this.externalId = externalId;
- }
-
- public @Nullable String getUserARN() {
- return userARN;
- }
+ /** AWS external ID, optional */
+ @Nullable
+ public abstract String getExternalId();
- public void setUserARN(@Nullable String userARN) {
- this.userARN = userARN;
- }
+ /** User ARN for the service principal */
+ @Nullable
+ public abstract String getUserARN();
- public @Nullable String getRegion() {
- return region;
- }
+ /** AWS region */
+ @Nullable
+ public abstract String getRegion();
- public void setRegion(@Nullable String region) {
- this.region = region;
- }
+ /** Endpoint URI for S3 API calls */
+ @Nullable
+ public abstract String getEndpoint();
+ /** Internal endpoint URI for S3 API calls */
@Nullable
- public String getEndpoint() {
- return endpoint;
- }
+ public abstract String getEndpointInternal();
@JsonIgnore
@Nullable
public URI getEndpointUri() {
- return endpoint == null ? null : URI.create(endpoint);
+ return getEndpoint() == null ? null : URI.create(getEndpoint());
}
@JsonIgnore
@Nullable
public URI getInternalEndpointUri() {
- return endpointInternal == null ? getEndpointUri() :
URI.create(endpointInternal);
+ return getEndpointInternal() == null ? getEndpointUri() :
URI.create(getEndpointInternal());
}
- /** Returns a flag indicating whether path-style bucket access should be
forced in S3 clients. */
- public @Nullable Boolean getPathStyleAccess() {
- return pathStyleAccess;
- }
+ /** Flag indicating whether path-style bucket access should be forced in S3
clients. */
+ public abstract @Nullable Boolean getPathStyleAccess();
+ /** Endpoint URI for STS API calls */
@Nullable
- public String getStsEndpoint() {
- return stsEndpoint;
- }
+ public abstract String getStsEndpoint();
/** Returns the STS endpoint if set, defaulting to {@link #getEndpointUri()}
otherwise. */
@JsonIgnore
@Nullable
public URI getStsEndpointUri() {
- return stsEndpoint == null ? getInternalEndpointUri() :
URI.create(stsEndpoint);
+ return getStsEndpoint() == null ? getInternalEndpointUri() :
URI.create(getStsEndpoint());
}
@JsonIgnore
public String getAwsAccountId() {
- return parseAwsAccountId(roleARN);
+ return parseAwsAccountId(getRoleARN());
}
@JsonIgnore
public String getAwsPartition() {
- return parseAwsPartition(roleARN);
+ return parseAwsPartition(getRoleARN());
}
private static String parseAwsAccountId(String arn) {
@@ -218,17 +146,4 @@ public class AwsStorageConfigurationInfo extends
PolarisStorageConfigurationInfo
throw new IllegalArgumentException("ARN does not match the expected role
ARN pattern");
}
}
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("storageType", getStorageType())
- .add("storageType", getStorageType().name())
- .add("roleARN", roleARN)
- .add("userARN", userARN)
- .add("externalId", externalId)
- .add("allowedLocation", getAllowedLocations())
- .add("region", region)
- .toString();
- }
}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/storage/azure/AzureStorageConfigurationInfo.java
b/polaris-core/src/main/java/org/apache/polaris/core/storage/azure/AzureStorageConfigurationInfo.java
index 53695b481..fb4d6c44a 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/storage/azure/AzureStorageConfigurationInfo.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/storage/azure/AzureStorageConfigurationInfo.java
@@ -18,36 +18,23 @@
*/
package org.apache.polaris.core.storage.azure;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.MoreObjects;
-import jakarta.annotation.Nonnull;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import jakarta.annotation.Nullable;
-import java.util.List;
import java.util.Objects;
import org.apache.polaris.core.storage.PolarisStorageConfigurationInfo;
+import org.apache.polaris.immutables.PolarisImmutable;
/** Azure storage configuration information. */
-public class AzureStorageConfigurationInfo extends
PolarisStorageConfigurationInfo {
+@PolarisImmutable
+@JsonSerialize(as = ImmutableAzureStorageConfigurationInfo.class)
+@JsonDeserialize(as = ImmutableAzureStorageConfigurationInfo.class)
+@JsonTypeName("AzureStorageConfigurationInfo")
+public abstract class AzureStorageConfigurationInfo extends
PolarisStorageConfigurationInfo {
- // Azure tenant id
- private final @Nonnull String tenantId;
-
- /** The multi tenant app name for the service principal */
- @JsonProperty(value = "multiTenantAppName", required = false)
- private @Nullable String multiTenantAppName = null;
-
- /** The consent url to the Azure permissions request page */
- @JsonProperty(value = "consentUrl", required = false)
- private @Nullable String consentUrl = null;
-
- @JsonCreator
- public AzureStorageConfigurationInfo(
- @JsonProperty(value = "allowedLocations", required = true) @Nonnull
- List<String> allowedLocations,
- @JsonProperty(value = "tenantId", required = true) @Nonnull String
tenantId) {
- super(StorageType.AZURE, allowedLocations);
- this.tenantId = tenantId;
+ public static ImmutableAzureStorageConfigurationInfo.Builder builder() {
+ return ImmutableAzureStorageConfigurationInfo.builder();
}
@Override
@@ -55,36 +42,21 @@ public class AzureStorageConfigurationInfo extends
PolarisStorageConfigurationIn
return "org.apache.iceberg.azure.adlsv2.ADLSFileIO";
}
- public @Nonnull String getTenantId() {
- return tenantId;
- }
-
- public @Nullable String getMultiTenantAppName() {
- return multiTenantAppName;
- }
-
- public void setMultiTenantAppName(@Nullable String multiTenantAppName) {
- this.multiTenantAppName = multiTenantAppName;
+ @Override
+ public StorageType getStorageType() {
+ return StorageType.AZURE;
}
- public @Nullable String getConsentUrl() {
- return consentUrl;
- }
+ /** Azure tenant ID. */
+ public abstract String getTenantId();
- public void setConsentUrl(@Nullable String consentUrl) {
- this.consentUrl = consentUrl;
- }
+ /** The multi tenant app name for the service principal */
+ @Nullable
+ public abstract String getMultiTenantAppName();
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("storageType", getStorageType())
- .add("tenantId", tenantId)
- .add("allowedLocation", getAllowedLocations())
- .add("multiTenantAppName", multiTenantAppName)
- .add("consentUrl", consentUrl)
- .toString();
- }
+ /** The consent url to the Azure permissions request page */
+ @Nullable
+ public abstract String getConsentUrl();
@Override
public void validatePrefixForStorageType(String loc) {
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/storage/gcp/GcpStorageConfigurationInfo.java
b/polaris-core/src/main/java/org/apache/polaris/core/storage/gcp/GcpStorageConfigurationInfo.java
index e664d4bd3..13f2da66d 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/storage/gcp/GcpStorageConfigurationInfo.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/storage/gcp/GcpStorageConfigurationInfo.java
@@ -18,26 +18,22 @@
*/
package org.apache.polaris.core.storage.gcp;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.MoreObjects;
-import jakarta.annotation.Nonnull;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import jakarta.annotation.Nullable;
-import java.util.List;
import org.apache.polaris.core.storage.PolarisStorageConfigurationInfo;
+import org.apache.polaris.immutables.PolarisImmutable;
/** Gcp storage storage configuration information. */
-public class GcpStorageConfigurationInfo extends
PolarisStorageConfigurationInfo {
-
- /** The gcp service account */
- @JsonProperty(value = "gcpServiceAccount", required = false)
- private @Nullable String gcpServiceAccount = null;
-
- @JsonCreator
- public GcpStorageConfigurationInfo(
- @JsonProperty(value = "allowedLocations", required = true) @Nonnull
- List<String> allowedLocations) {
- super(StorageType.GCS, allowedLocations);
+@PolarisImmutable
+@JsonSerialize(as = ImmutableGcpStorageConfigurationInfo.class)
+@JsonDeserialize(as = ImmutableGcpStorageConfigurationInfo.class)
+@JsonTypeName("GcpStorageConfigurationInfo")
+public abstract class GcpStorageConfigurationInfo extends
PolarisStorageConfigurationInfo {
+
+ public static ImmutableGcpStorageConfigurationInfo.Builder builder() {
+ return ImmutableGcpStorageConfigurationInfo.builder();
}
@Override
@@ -45,20 +41,12 @@ public class GcpStorageConfigurationInfo extends
PolarisStorageConfigurationInfo
return "org.apache.iceberg.gcp.gcs.GCSFileIO";
}
- public void setGcpServiceAccount(@Nullable String gcpServiceAccount) {
- this.gcpServiceAccount = gcpServiceAccount;
- }
-
- public @Nullable String getGcpServiceAccount() {
- return gcpServiceAccount;
- }
-
@Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("storageType", getStorageType())
- .add("allowedLocation", getAllowedLocations())
- .add("gcpServiceAccount", gcpServiceAccount)
- .toString();
+ public StorageType getStorageType() {
+ return StorageType.GCS;
}
+
+ /** The gcp service account */
+ @Nullable
+ public abstract String getGcpServiceAccount();
}
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/storage/InMemoryStorageIntegrationTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/storage/InMemoryStorageIntegrationTest.java
index 47a760f03..1bf6e4bb2 100644
---
a/polaris-core/src/test/java/org/apache/polaris/core/storage/InMemoryStorageIntegrationTest.java
+++
b/polaris-core/src/test/java/org/apache/polaris/core/storage/InMemoryStorageIntegrationTest.java
@@ -20,7 +20,6 @@ package org.apache.polaris.core.storage;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.polaris.core.config.PolarisConfigurationStore;
@@ -48,14 +47,14 @@ class InMemoryStorageIntegrationTest {
Map<String, Map<PolarisStorageActions,
PolarisStorageIntegration.ValidationResult>> result =
storage.validateAccessToLocations(
realmConfig,
- new AwsStorageConfigurationInfo(
- PolarisStorageConfigurationInfo.StorageType.S3,
- List.of(
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocations(
allowedScheme + "://bucket/path/to/warehouse",
allowedScheme + "://bucket/anotherpath/to/warehouse",
- allowedScheme + "://bucket2/warehouse/"),
- "arn:aws:iam::012345678901:role/jdoe",
- "us-east-2"),
+ allowedScheme + "://bucket2/warehouse/")
+ .roleARN("arn:aws:iam::012345678901:role/jdoe")
+ .region("us-east-2")
+ .build(),
Set.of(PolarisStorageActions.READ),
Set.of(
locationScheme + "://bucket/path/to/warehouse/namespace/table",
@@ -83,11 +82,11 @@ class InMemoryStorageIntegrationTest {
@Test
public void testAwsAccountIdParsing() {
AwsStorageConfigurationInfo awsConfig =
- new AwsStorageConfigurationInfo(
- PolarisStorageConfigurationInfo.StorageType.S3,
- List.of("s3://bucket/path/to/warehouse"),
- "arn:aws:iam::012345678901:role/jdoe",
- "us-east-2");
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation("s3://bucket/path/to/warehouse")
+ .roleARN("arn:aws:iam::012345678901:role/jdoe")
+ .region("us-east-2")
+ .build();
String expectedAccountId = "012345678901";
String actualAccountId = awsConfig.getAwsAccountId();
@@ -105,7 +104,7 @@ class InMemoryStorageIntegrationTest {
Map<String, Map<PolarisStorageActions,
PolarisStorageIntegration.ValidationResult>> result =
storage.validateAccessToLocations(
realmConfig,
- new FileStorageConfigurationInfo(List.of("file://", "*")),
+
FileStorageConfigurationInfo.builder().addAllowedLocations("file://",
"*").build(),
Set.of(PolarisStorageActions.READ),
Set.of(
s3Scheme + "://bucket/path/to/warehouse/namespace/table",
@@ -147,11 +146,10 @@ class InMemoryStorageIntegrationTest {
Map<String, Map<PolarisStorageActions,
PolarisStorageIntegration.ValidationResult>> result =
storage.validateAccessToLocations(
realmConfig,
- new AwsStorageConfigurationInfo(
- PolarisStorageConfigurationInfo.StorageType.S3,
- List.of(),
- "arn:aws:iam::012345678901:role/jdoe",
- "us-east-2"),
+ AwsStorageConfigurationInfo.builder()
+ .roleARN("arn:aws:iam::012345678901:role/jdoe")
+ .region("us-east-2")
+ .build(),
Set.of(PolarisStorageActions.READ),
Set.of(
"s3://bucket/path/to/warehouse/namespace/table",
@@ -184,11 +182,11 @@ class InMemoryStorageIntegrationTest {
Map<String, Map<PolarisStorageActions,
PolarisStorageIntegration.ValidationResult>> result =
storage.validateAccessToLocations(
realmConfig,
- new AwsStorageConfigurationInfo(
- PolarisStorageConfigurationInfo.StorageType.S3,
- List.of("s3://bucket/path/to/warehouse"),
- "arn:aws:iam::012345678901:role/jdoe",
- "us-east-2"),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation("s3://bucket/path/to/warehouse")
+ .roleARN("arn:aws:iam::012345678901:role/jdoe")
+ .region("us-east-2")
+ .build(),
Set.of(PolarisStorageActions.READ),
// trying to read a prefix under the allowed location
Set.of("s3://bucket/path/to"));
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfoTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfoTest.java
index 8605b8142..faca7193f 100644
---
a/polaris-core/src/test/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfoTest.java
+++
b/polaris-core/src/test/java/org/apache/polaris/core/storage/aws/AwsStorageConfigurationInfoTest.java
@@ -19,53 +19,44 @@
package org.apache.polaris.core.storage.aws;
-import static
org.apache.polaris.core.storage.PolarisStorageConfigurationInfo.StorageType.S3;
import static org.assertj.core.api.Assertions.assertThat;
import java.net.URI;
-import java.util.List;
import org.junit.jupiter.api.Test;
public class AwsStorageConfigurationInfoTest {
- private static AwsStorageConfigurationInfo config(String endpoint, String
stsEndpoint) {
- return config(endpoint, stsEndpoint, false);
- }
-
- private static AwsStorageConfigurationInfo config(
- String endpoint, String stsEndpoint, Boolean pathStyle) {
- return config(endpoint, stsEndpoint, pathStyle, null);
- }
-
- private static AwsStorageConfigurationInfo config(
- String endpoint, String stsEndpoint, Boolean pathStyle, String
internalEndpoint) {
- return new AwsStorageConfigurationInfo(
- S3, List.of(), "role", null, null, endpoint, stsEndpoint, pathStyle,
internalEndpoint);
- }
-
@Test
public void testStsEndpoint() {
- assertThat(config(null, null))
+ assertThat(newBuilder().build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getStsEndpointUri)
.containsExactly(null, null);
- assertThat(config(null, "http://sts.example.com"))
+ assertThat(newBuilder().stsEndpoint("http://sts.example.com").build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getStsEndpointUri)
.containsExactly(null, URI.create("http://sts.example.com"));
- assertThat(config("http://s3.example.com", null))
+ assertThat(newBuilder().endpoint("http://s3.example.com").build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getStsEndpointUri)
.containsExactly(URI.create("http://s3.example.com"),
URI.create("http://s3.example.com"));
- assertThat(config("http://s3.example.com", "http://sts.example.com"))
+ assertThat(
+ newBuilder()
+ .endpoint("http://s3.example.com")
+ .stsEndpoint("http://sts.example.com")
+ .build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getStsEndpointUri)
.containsExactly(URI.create("http://s3.example.com"),
URI.create("http://sts.example.com"));
- assertThat(config("http://s3.example.com", null, false,
"http://int.example.com"))
+ assertThat(
+ newBuilder()
+ .endpoint("http://s3.example.com")
+ .endpointInternal("http://int.example.com")
+ .build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getStsEndpointUri,
@@ -76,31 +67,42 @@ public class AwsStorageConfigurationInfoTest {
URI.create("http://int.example.com"));
}
+ private static ImmutableAwsStorageConfigurationInfo.Builder newBuilder() {
+ return AwsStorageConfigurationInfo.builder().roleARN("role");
+ }
+
@Test
public void testInternalEndpoint() {
- assertThat(config(null, null))
+ assertThat(newBuilder().build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getInternalEndpointUri)
.containsExactly(null, null);
- assertThat(config(null, "http://sts.example.com"))
+ assertThat(newBuilder().stsEndpoint("http://sts.example.com").build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getInternalEndpointUri)
.containsExactly(null, null);
- assertThat(config("http://s3.example.com", null))
+ assertThat(newBuilder().endpoint("http://s3.example.com").build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getInternalEndpointUri)
.containsExactly(URI.create("http://s3.example.com"),
URI.create("http://s3.example.com"));
assertThat(
- config(
- "http://s3.example.com", "http://sts.example.com", false,
"http://int.example.com"))
+ newBuilder()
+ .endpoint("http://s3.example.com")
+ .stsEndpoint("http://sts.example.com")
+ .endpointInternal("http://int.example.com")
+ .build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getInternalEndpointUri)
.containsExactly(URI.create("http://s3.example.com"),
URI.create("http://int.example.com"));
- assertThat(config(null, "http://sts.example.com", false,
"http://int.example.com"))
+ assertThat(
+ newBuilder()
+ .stsEndpoint("http://sts.example.com")
+ .endpointInternal("http://int.example.com")
+ .build())
.extracting(
AwsStorageConfigurationInfo::getEndpointUri,
AwsStorageConfigurationInfo::getInternalEndpointUri)
@@ -109,8 +111,8 @@ public class AwsStorageConfigurationInfoTest {
@Test
public void testPathStyleAccess() {
- assertThat(config(null, null, null).getPathStyleAccess()).isNull();
- assertThat(config(null, null, false).getPathStyleAccess()).isFalse();
- assertThat(config(null, null, true).getPathStyleAccess()).isTrue();
+
assertThat(newBuilder().pathStyleAccess(null).build().getPathStyleAccess()).isNull();
+
assertThat(newBuilder().pathStyleAccess(false).build().getPathStyleAccess()).isFalse();
+
assertThat(newBuilder().pathStyleAccess(true).build().getPathStyleAccess()).isTrue();
}
}
diff --git
a/polaris-core/src/test/java/org/apache/polaris/service/storage/PolarisStorageConfigurationInfoTest.java
b/polaris-core/src/test/java/org/apache/polaris/service/storage/PolarisStorageConfigurationInfoTest.java
new file mode 100644
index 000000000..fe15147ed
--- /dev/null
+++
b/polaris-core/src/test/java/org/apache/polaris/service/storage/PolarisStorageConfigurationInfoTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.polaris.service.storage;
+
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.stream.Stream;
+import org.apache.polaris.core.storage.FileStorageConfigurationInfo;
+import org.apache.polaris.core.storage.PolarisStorageConfigurationInfo;
+import org.apache.polaris.core.storage.aws.AwsStorageConfigurationInfo;
+import org.apache.polaris.core.storage.azure.AzureStorageConfigurationInfo;
+import org.apache.polaris.core.storage.gcp.GcpStorageConfigurationInfo;
+import org.assertj.core.api.SoftAssertions;
+import org.assertj.core.api.junit.jupiter.InjectSoftAssertions;
+import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+@ExtendWith(SoftAssertionsExtension.class)
+public class PolarisStorageConfigurationInfoTest {
+ @InjectSoftAssertions protected SoftAssertions soft;
+
+ private static ObjectMapper mapper;
+
+ @BeforeAll
+ public static void setup() {
+ mapper = new ObjectMapper();
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ public void reserialization(PolarisStorageConfigurationInfo configInfo,
String serialized)
+ throws Exception {
+ var jsonStr = configInfo.serialize();
+
+ var asJsonNode = mapper.readValue(jsonStr, JsonNode.class);
+ var serializedJsonNode = mapper.readValue(serialized, JsonNode.class);
+ soft.assertThat(asJsonNode).isEqualTo(serializedJsonNode);
+
+ var deserialized = mapper.readValue(serialized,
PolarisStorageConfigurationInfo.class);
+ soft.assertThat(deserialized).isEqualTo(configInfo);
+
+ var reserialized = mapper.readValue(jsonStr,
PolarisStorageConfigurationInfo.class);
+ soft.assertThat(reserialized).isEqualTo(configInfo);
+ }
+
+ static Stream<Arguments> reserialization() {
+ return Stream.of(
+ arguments(
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocations("s3://foo/bar", "s3://no/where")
+ .roleARN("arn:foo")
+ .region("no-where-1")
+ .build(),
+
"{\"@type\":\"AwsStorageConfigurationInfo\",\"storageType\":\"S3\",\"allowedLocations\":[\"s3://foo/bar\",\"s3://no/where\"],\"roleARN\":\"arn:foo\",\"region\":\"no-where-1\",\"fileIoImplClassName\":\"org.apache.iceberg.aws.s3.S3FileIO\"}"),
+ arguments(
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocations("s3://foo/bar", "s3://no/where")
+ .region("no-where-1")
+ .roleARN("arn:foo")
+ .externalId("external-id")
+ .build(),
+
"{\"@type\":\"AwsStorageConfigurationInfo\",\"storageType\":\"S3\",\"allowedLocations\":[\"s3://foo/bar\",\"s3://no/where\"],\"roleARN\":\"arn:foo\",\"externalId\":\"external-id\",\"region\":\"no-where-1\",\"fileIoImplClassName\":\"org.apache.iceberg.aws.s3.S3FileIO\"}"),
+ arguments(
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocations("s3://foo/bar", "s3://no/where")
+ .region("no-where-1")
+ .roleARN("arn:foo")
+ .externalId("external-id")
+ .endpoint("http://127.9.9.9/")
+ .stsEndpoint("http://127.9.9.9/sts/")
+ .endpointInternal("http://127.8.8.8/internal/")
+ .pathStyleAccess(true)
+ .build(),
+
"{\"@type\":\"AwsStorageConfigurationInfo\",\"storageType\":\"S3\",\"allowedLocations\":[\"s3://foo/bar\",\"s3://no/where\"],\"roleARN\":\"arn:foo\",\"externalId\":\"external-id\",\"region\":\"no-where-1\",\"endpoint\":\"http://127.9.9.9/\",\"stsEndpoint\":\"http://127.9.9.9/sts/\",\"endpointInternal\":\"http://127.8.8.8/internal/\",\"pathStyleAccess\":true,\"fileIoImplClassName\":\"org.apache.iceberg.aws.s3.S3FileIO\"}"),
+ //
+ arguments(
+ GcpStorageConfigurationInfo.builder()
+ .addAllowedLocations("gs://foo/bar", "gs://meep/moo")
+ .build(),
+
"{\"@type\":\"GcpStorageConfigurationInfo\",\"allowedLocations\":[\"gs://foo/bar\",\"gs://meep/moo\"],\"storageType\":\"GCS\",\"fileIoImplClassName\":\"org.apache.iceberg.gcp.gcs.GCSFileIO\"}"),
+ //
+ arguments(
+ AzureStorageConfigurationInfo.builder()
+ .addAllowedLocations("abfs://[email protected]/",
"abfss://[email protected]/")
+ .tenantId("tenant-id")
+ .build(),
+
"{\"@type\":\"AzureStorageConfigurationInfo\",\"allowedLocations\":[\"abfs://[email protected]/\",\"abfss://[email protected]/\"],\"tenantId\":\"tenant-id\",\"storageType\":\"AZURE\",\"fileIoImplClassName\":\"org.apache.iceberg.azure.adlsv2.ADLSFileIO\"}"),
+ //
+ arguments(
+ FileStorageConfigurationInfo.builder()
+ .addAllowedLocations("file:///tmp/bar", "file:///meep/moo")
+ .build(),
+
"{\"@type\":\"FileStorageConfigurationInfo\",\"allowedLocations\":[\"file:///tmp/bar\",\"file:///meep/moo\"],\"storageType\":\"FILE\",\"fileIoImplClassName\":\"org.apache.iceberg.hadoop.HadoopFileIO\"}"));
+ }
+}
diff --git
a/polaris-core/src/test/java/org/apache/polaris/service/storage/aws/AwsCredentialsStorageIntegrationTest.java
b/polaris-core/src/test/java/org/apache/polaris/service/storage/aws/AwsCredentialsStorageIntegrationTest.java
index 604086a29..10ba4b908 100644
---
a/polaris-core/src/test/java/org/apache/polaris/service/storage/aws/AwsCredentialsStorageIntegrationTest.java
+++
b/polaris-core/src/test/java/org/apache/polaris/service/storage/aws/AwsCredentialsStorageIntegrationTest.java
@@ -18,7 +18,6 @@
*/
package org.apache.polaris.service.storage.aws;
-import static
org.apache.polaris.core.storage.PolarisStorageConfigurationInfo.StorageType.S3;
import static org.assertj.core.api.Assertions.assertThat;
import jakarta.annotation.Nonnull;
@@ -27,7 +26,6 @@ import java.util.List;
import java.util.Set;
import org.apache.polaris.core.storage.AccessConfig;
import org.apache.polaris.core.storage.BaseStorageIntegrationTest;
-import org.apache.polaris.core.storage.PolarisStorageConfigurationInfo;
import org.apache.polaris.core.storage.StorageAccessProperty;
import org.apache.polaris.core.storage.aws.AwsCredentialsStorageIntegration;
import org.apache.polaris.core.storage.aws.AwsStorageConfigurationInfo;
@@ -87,8 +85,11 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
String warehouseDir = scheme + "://bucket/path/to/warehouse";
AccessConfig accessConfig =
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- S3, List.of(warehouseDir), roleARN, externalId, null),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(warehouseDir)
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG,
@@ -108,7 +109,6 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
@ParameterizedTest
@ValueSource(strings = {AWS_PARTITION, "aws-cn", "aws-us-gov"})
public void testGetSubscopedCredsInlinePolicy(String awsPartition) {
- PolarisStorageConfigurationInfo.StorageType storageType = S3;
String roleARN;
String region;
switch (awsPartition) {
@@ -231,12 +231,12 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
Assertions.assertThatThrownBy(
() ->
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- storageType,
- List.of(s3Path(bucket, warehouseKeyPrefix)),
- roleARN,
- externalId,
- region),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket,
warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .region(region)
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG,
@@ -249,12 +249,12 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
case "aws-us-gov":
AccessConfig accessConfig =
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- storageType,
- List.of(s3Path(bucket, warehouseKeyPrefix)),
- roleARN,
- externalId,
- region),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket, warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .region(region)
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG,
@@ -349,12 +349,12 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
});
AccessConfig accessConfig =
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- S3,
- List.of(s3Path(bucket, warehouseKeyPrefix)),
- roleARN,
- externalId,
- "us-east-2"),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket, warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .region("us-east-2")
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG,
@@ -443,12 +443,12 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
});
AccessConfig accessConfig =
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- S3,
- List.of(s3Path(bucket, warehouseKeyPrefix)),
- roleARN,
- externalId,
- "us-east-2"),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket, warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .region("us-east-2")
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG,
@@ -509,12 +509,12 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
});
AccessConfig accessConfig =
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- S3,
- List.of(s3Path(bucket, warehouseKeyPrefix)),
- roleARN,
- externalId,
- "us-east-2"),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket, warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .region("us-east-2")
+ .build(),
stsClient)
.getSubscopedCreds(EMPTY_REALM_CONFIG, true, /* allowList = true
*/ Set.of(), Set.of());
assertThat(accessConfig.credentials())
@@ -546,12 +546,12 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
Assertions.assertThatThrownBy(
() ->
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- S3,
- List.of(s3Path(bucket, warehouseKeyPrefix)),
- roleARN,
- externalId,
- clientRegion),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket,
warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .region(clientRegion)
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG, true, /* allowList = true */
Set.of(), Set.of()))
@@ -561,12 +561,12 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
case "aws-us-gov":
AccessConfig accessConfig =
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- S3,
- List.of(s3Path(bucket, warehouseKeyPrefix)),
- roleARN,
- externalId,
- clientRegion),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket, warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .region(clientRegion)
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG, true, /* allowList = true */ Set.of(),
Set.of());
@@ -597,8 +597,11 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
case AWS_PARTITION:
AccessConfig accessConfig =
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- S3, List.of(s3Path(bucket, warehouseKeyPrefix)),
roleARN, externalId, null),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket, warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG, true, /* allowList = true */ Set.of(),
Set.of());
@@ -611,12 +614,11 @@ class AwsCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
Assertions.assertThatThrownBy(
() ->
new AwsCredentialsStorageIntegration(
- new AwsStorageConfigurationInfo(
- PolarisStorageConfigurationInfo.StorageType.S3,
- List.of(s3Path(bucket, warehouseKeyPrefix)),
- roleARN,
- externalId,
- null),
+ AwsStorageConfigurationInfo.builder()
+ .addAllowedLocation(s3Path(bucket,
warehouseKeyPrefix))
+ .roleARN(roleARN)
+ .externalId(externalId)
+ .build(),
stsClient)
.getSubscopedCreds(
EMPTY_REALM_CONFIG, true, /* allowList = true */
Set.of(), Set.of()))
diff --git
a/polaris-core/src/test/java/org/apache/polaris/service/storage/azure/AzureCredentialStorageIntegrationTest.java
b/polaris-core/src/test/java/org/apache/polaris/service/storage/azure/AzureCredentialStorageIntegrationTest.java
index d93dcc63f..768f4c330 100644
---
a/polaris-core/src/test/java/org/apache/polaris/service/storage/azure/AzureCredentialStorageIntegrationTest.java
+++
b/polaris-core/src/test/java/org/apache/polaris/service/storage/azure/AzureCredentialStorageIntegrationTest.java
@@ -340,11 +340,12 @@ public class AzureCredentialStorageIntegrationTest
extends BaseStorageIntegratio
private AccessConfig subscopedCredsForOperations(
List<String> allowedReadLoc, List<String> allowedWriteLoc, boolean
allowListAction) {
- List<String> allowedLoc = new ArrayList<>();
- allowedLoc.addAll(allowedReadLoc);
- allowedLoc.addAll(allowedWriteLoc);
AzureStorageConfigurationInfo azureConfig =
- new AzureStorageConfigurationInfo(allowedLoc, tenantId);
+ AzureStorageConfigurationInfo.builder()
+ .addAllAllowedLocations(allowedReadLoc)
+ .addAllAllowedLocations(allowedWriteLoc)
+ .tenantId(tenantId)
+ .build();
AzureCredentialsStorageIntegration azureCredsIntegration =
new AzureCredentialsStorageIntegration(azureConfig);
return azureCredsIntegration.getSubscopedCreds(
diff --git
a/polaris-core/src/test/java/org/apache/polaris/service/storage/gcp/GcpCredentialsStorageIntegrationTest.java
b/polaris-core/src/test/java/org/apache/polaris/service/storage/gcp/GcpCredentialsStorageIntegrationTest.java
index e0985199b..da890627e 100644
---
a/polaris-core/src/test/java/org/apache/polaris/service/storage/gcp/GcpCredentialsStorageIntegrationTest.java
+++
b/polaris-core/src/test/java/org/apache/polaris/service/storage/gcp/GcpCredentialsStorageIntegrationTest.java
@@ -37,7 +37,6 @@ import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageException;
import com.google.cloud.storage.StorageOptions;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
@@ -157,10 +156,11 @@ class GcpCredentialsStorageIntegrationTest extends
BaseStorageIntegrationTest {
private AccessConfig subscopedCredsForOperations(
List<String> allowedReadLoc, List<String> allowedWriteLoc, boolean
allowListAction)
throws IOException {
- List<String> allowedLoc = new ArrayList<>();
- allowedLoc.addAll(allowedReadLoc);
- allowedLoc.addAll(allowedWriteLoc);
- GcpStorageConfigurationInfo gcpConfig = new
GcpStorageConfigurationInfo(allowedLoc);
+ GcpStorageConfigurationInfo gcpConfig =
+ GcpStorageConfigurationInfo.builder()
+ .addAllAllowedLocations(allowedReadLoc)
+ .addAllAllowedLocations(allowedWriteLoc)
+ .build();
GcpCredentialsStorageIntegration gcpCredsIntegration =
new GcpCredentialsStorageIntegration(
gcpConfig,