Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions integration-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ dependencies {

implementation(platform(libs.junit.bom))
implementation("org.junit.jupiter:junit-jupiter")
implementation("org.junit.jupiter:junit-jupiter-api")
compileOnly("org.junit.jupiter:junit-jupiter-engine")
implementation(libs.assertj.core)
implementation(libs.mockito.core)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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.it.env;

import com.google.common.annotations.VisibleForTesting;
import java.net.URI;
import java.nio.file.Path;
import java.util.function.Function;

public final class IntegrationTestsHelper {

/**
* The environment variable that can be used to override the temporary directory used by the
* integration tests.
*/
public static final String INTEGRATION_TEST_TEMP_DIR_ENV_VAR = "INTEGRATION_TEST_TEMP_DIR";

private IntegrationTestsHelper() {}

/**
* Get the temporary directory to use for integration tests.
*
* <p>If the environment variable {@link #INTEGRATION_TEST_TEMP_DIR_ENV_VAR} is set, it will be
* used as the temporary directory. Otherwise, the default local temporary directory will be used.
*
* <p>The environment variable should be a URI, e.g. {@code "file:///tmp/polaris"} or {@code
* "s3://bucket/polaris"}. If the URI does not have a scheme, it will be assumed to be a local
* file URI.
*/
public static URI getTemporaryDirectory(Path defaultLocalDirectory) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be lovely if Path could be annotated with @TempDir but unfortunately that does not work:

junit-team/junit-framework#1786

return getTemporaryDirectory(System::getenv, defaultLocalDirectory);
}

@VisibleForTesting
static URI getTemporaryDirectory(Function<String, String> getenv, Path defaultLocalDirectory) {
String envVar = getenv.apply(INTEGRATION_TEST_TEMP_DIR_ENV_VAR);
envVar = envVar != null ? envVar : defaultLocalDirectory.toString();
envVar = envVar.startsWith("/") ? "file://" + envVar : envVar;
return URI.create(envVar + "/").normalize();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import java.io.IOException;
import java.nio.file.Files;
import java.net.URI;
import java.nio.file.Path;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.iceberg.BaseTable;
import org.apache.iceberg.PartitionData;
Expand Down Expand Up @@ -75,6 +74,7 @@
import org.apache.polaris.core.entity.PolarisEntityConstants;
import org.apache.polaris.service.it.env.ClientCredentials;
import org.apache.polaris.service.it.env.ClientPrincipal;
import org.apache.polaris.service.it.env.IntegrationTestsHelper;
import org.apache.polaris.service.it.env.PolarisApiEndpoints;
import org.apache.polaris.service.it.env.PolarisClient;
import org.apache.polaris.service.it.env.RestApi;
Expand All @@ -87,6 +87,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

Expand All @@ -109,7 +110,6 @@ public class PolarisApplicationIntegrationTest {

public static final String PRINCIPAL_ROLE_ALL = "PRINCIPAL_ROLE:ALL";

private static Path testDir;
private static String realm;

private static RestApi managementApi;
Expand All @@ -118,25 +118,22 @@ public class PolarisApplicationIntegrationTest {
private static ClientCredentials clientCredentials;
private static ClientPrincipal admin;
private static String authToken;
private static URI baseLocation;

private String principalRoleName;
private String internalCatalogName;

@BeforeAll
public static void setup(PolarisApiEndpoints apiEndpoints, ClientPrincipal adminCredentials)
throws IOException {
public static void setup(
PolarisApiEndpoints apiEndpoints, ClientPrincipal adminCredentials, @TempDir Path tempDir) {
endpoints = apiEndpoints;
client = polarisClient(endpoints);
realm = endpoints.realmId();
admin = adminCredentials;
clientCredentials = adminCredentials.credentials();
authToken = client.obtainToken(clientCredentials);

testDir = Path.of("build/test_data/iceberg/" + realm);
FileUtils.deleteQuietly(testDir.toFile());
Files.createDirectories(testDir);

managementApi = client.managementApi(clientCredentials);
baseLocation = IntegrationTestsHelper.getTemporaryDirectory(tempDir).resolve(realm + "/");
}

@AfterAll
Expand Down Expand Up @@ -443,19 +440,17 @@ public void testIcebergRegisterTableInExternalCatalog() throws IOException {
Catalog.TypeEnum.EXTERNAL,
principalRoleName,
FileStorageConfigInfo.builder(StorageConfigInfo.StorageTypeEnum.FILE)
.setAllowedLocations(List.of("file://" + testDir.toFile().getAbsolutePath()))
.setAllowedLocations(List.of(baseLocation.toString()))
.build(),
"file://" + testDir.toFile().getAbsolutePath());
baseLocation.toString());
try (RESTSessionCatalog sessionCatalog = newSessionCatalog(catalogName);
HadoopFileIO fileIo = new HadoopFileIO(new Configuration())) {
SessionCatalog.SessionContext sessionContext = SessionCatalog.SessionContext.createEmpty();
Namespace ns = Namespace.of("db1");
sessionCatalog.createNamespace(sessionContext, ns);
TableIdentifier tableIdentifier = TableIdentifier.of(ns, "the_table");
String location =
"file://"
+ testDir.toFile().getAbsolutePath()
+ "/testIcebergRegisterTableInExternalCatalog";
baseLocation.resolve("testIcebergRegisterTableInExternalCatalog").toString();
String metadataLocation = location + "/metadata/000001-494949494949494949.metadata.json";

TableMetadata tableMetadata =
Expand Down Expand Up @@ -489,19 +484,16 @@ public void testIcebergUpdateTableInExternalCatalog() throws IOException {
Catalog.TypeEnum.EXTERNAL,
principalRoleName,
FileStorageConfigInfo.builder(StorageConfigInfo.StorageTypeEnum.FILE)
.setAllowedLocations(List.of("file://" + testDir.toFile().getAbsolutePath()))
.setAllowedLocations(List.of(baseLocation.toString()))
.build(),
"file://" + testDir.toFile().getAbsolutePath());
baseLocation.toString());
try (RESTSessionCatalog sessionCatalog = newSessionCatalog(catalogName);
HadoopFileIO fileIo = new HadoopFileIO(new Configuration())) {
SessionCatalog.SessionContext sessionContext = SessionCatalog.SessionContext.createEmpty();
Namespace ns = Namespace.of("db1");
sessionCatalog.createNamespace(sessionContext, ns);
TableIdentifier tableIdentifier = TableIdentifier.of(ns, "the_table");
String location =
"file://"
+ testDir.toFile().getAbsolutePath()
+ "/testIcebergUpdateTableInExternalCatalog";
String location = baseLocation.resolve("testIcebergUpdateTableInExternalCatalog").toString();
String metadataLocation = location + "/metadata/000001-494949494949494949.metadata.json";

Types.NestedField col1 = Types.NestedField.of(1, false, "col1", Types.StringType.get());
Expand Down Expand Up @@ -541,20 +533,16 @@ public void testIcebergDropTableInExternalCatalog() throws IOException {
Catalog.TypeEnum.EXTERNAL,
principalRoleName,
FileStorageConfigInfo.builder(StorageConfigInfo.StorageTypeEnum.FILE)
.setAllowedLocations(List.of("file://" + testDir.toFile().getAbsolutePath()))
.setAllowedLocations(List.of(baseLocation.toString()))
.build(),
"file://" + testDir.toFile().getAbsolutePath());
baseLocation.toString());
try (RESTSessionCatalog sessionCatalog = newSessionCatalog(catalogName);
HadoopFileIO fileIo = new HadoopFileIO(new Configuration())) {
SessionCatalog.SessionContext sessionContext = SessionCatalog.SessionContext.createEmpty();
Namespace ns = Namespace.of("db1");
sessionCatalog.createNamespace(sessionContext, ns);
TableIdentifier tableIdentifier = TableIdentifier.of(ns, "the_table");
String location =
"file://"
+ testDir.toFile().getAbsolutePath()
+ "/"
+ "testIcebergDropTableInExternalCatalog";
String location = baseLocation.resolve("testIcebergDropTableInExternalCatalog").toString();
String metadataLocation = location + "/metadata/000001-494949494949494949.metadata.json";

TableMetadata tableMetadata =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -79,6 +81,7 @@
import org.apache.polaris.service.it.env.CatalogApi;
import org.apache.polaris.service.it.env.ClientCredentials;
import org.apache.polaris.service.it.env.IcebergHelper;
import org.apache.polaris.service.it.env.IntegrationTestsHelper;
import org.apache.polaris.service.it.env.ManagementApi;
import org.apache.polaris.service.it.env.PolarisApiEndpoints;
import org.apache.polaris.service.it.env.PolarisClient;
Expand All @@ -92,6 +95,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;

/**
* Import the full core Iceberg catalog tests by hitting the REST service via the RESTCatalog
Expand All @@ -108,9 +112,9 @@ public class PolarisRestCatalogIntegrationTest extends CatalogTests<RESTCatalog>
private static final String TEST_ROLE_ARN =
Optional.ofNullable(System.getenv("INTEGRATION_TEST_ROLE_ARN"))
.orElse("arn:aws:iam::123456789012:role/my-role");
private static final String S3_BUCKET_BASE =
Optional.ofNullable(System.getenv("INTEGRATION_TEST_S3_PATH"))
.orElse("file:///tmp/buckets/my-bucket");

private static URI s3BucketBase;
private static URI externalCatalogBase;

protected static final String VIEW_QUERY = "select * from ns1.layer1_table";
private static String principalRoleName;
Expand All @@ -125,7 +129,7 @@ public class PolarisRestCatalogIntegrationTest extends CatalogTests<RESTCatalog>
private String currentCatalogName;

private final String catalogBaseLocation =
S3_BUCKET_BASE + "/" + System.getenv("USER") + "/path/to/data";
s3BucketBase + "/" + System.getenv("USER") + "/path/to/data";

private static final String[] DEFAULT_CATALOG_PROPERTIES = {
"allow.unstructured.table.location", "true",
Expand All @@ -148,7 +152,8 @@ String[] properties() default {
}

@BeforeAll
static void setup(PolarisApiEndpoints apiEndpoints, ClientCredentials credentials) {
static void setup(
PolarisApiEndpoints apiEndpoints, ClientCredentials credentials, @TempDir Path tempDir) {
adminCredentials = credentials;
endpoints = apiEndpoints;
client = polarisClient(endpoints);
Expand All @@ -157,6 +162,9 @@ static void setup(PolarisApiEndpoints apiEndpoints, ClientCredentials credential
principalRoleName = client.newEntityName("rest-admin");
principalCredentials = managementApi.createPrincipalWithRole(principalName, principalRoleName);
catalogApi = client.catalogApi(principalCredentials);
URI testRootUri = IntegrationTestsHelper.getTemporaryDirectory(tempDir);
s3BucketBase = testRootUri.resolve("my-bucket");
externalCatalogBase = testRootUri.resolve("external-catalog");
}

@AfterAll
Expand Down Expand Up @@ -192,7 +200,7 @@ public void before(TestInfo testInfo) {
for (int i = 0; i < properties.length; i += 2) {
catalogPropsBuilder.addProperty(properties[i], properties[i + 1]);
}
if (!S3_BUCKET_BASE.startsWith("file:/")) {
if (!s3BucketBase.getScheme().equals("file")) {
catalogPropsBuilder.addProperty(
CatalogEntity.REPLACE_NEW_LOCATION_PREFIX_WITH_CATALOG_DEFAULT_KEY, "file:");
}
Expand All @@ -202,7 +210,7 @@ public void before(TestInfo testInfo) {
.setName(currentCatalogName)
.setProperties(catalogPropsBuilder.build())
.setStorageConfigInfo(
S3_BUCKET_BASE.startsWith("file:/")
s3BucketBase.getScheme().equals("file")
? new FileStorageConfigInfo(
StorageConfigInfo.StorageTypeEnum.FILE, List.of("file://"))
: awsConfigModel)
Expand Down Expand Up @@ -541,12 +549,12 @@ public void testLoadTableWithAccessDelegationForExternalCatalogWithConfigDisable
TableMetadata.newTableMetadata(
new Schema(List.of(Types.NestedField.of(1, false, "col1", new Types.StringType()))),
PartitionSpec.unpartitioned(),
"file:///tmp/ns1/my_table",
externalCatalogBase + "/ns1/my_table",
Map.of());
try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
resolvingFileIO.initialize(Map.of());
resolvingFileIO.setConf(new Configuration());
String fileLocation = "file:///tmp/ns1/my_table/metadata/v1.metadata.json";
String fileLocation = externalCatalogBase + "/ns1/my_table/metadata/v1.metadata.json";
TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
restCatalog.registerTable(TableIdentifier.of(ns1, "my_table"), fileLocation);
try {
Expand Down Expand Up @@ -576,12 +584,12 @@ public void testLoadTableWithoutAccessDelegationForExternalCatalogWithConfigDisa
TableMetadata.newTableMetadata(
new Schema(List.of(Types.NestedField.of(1, false, "col1", new Types.StringType()))),
PartitionSpec.unpartitioned(),
"file:///tmp/ns1/my_table",
externalCatalogBase + "/ns1/my_table",
Map.of());
try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
resolvingFileIO.initialize(Map.of());
resolvingFileIO.setConf(new Configuration());
String fileLocation = "file:///tmp/ns1/my_table/metadata/v1.metadata.json";
String fileLocation = externalCatalogBase + "/ns1/my_table/metadata/v1.metadata.json";
TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
restCatalog.registerTable(TableIdentifier.of(ns1, "my_table"), fileLocation);
try {
Expand Down Expand Up @@ -610,12 +618,12 @@ public void testLoadTableWithAccessDelegationForExternalCatalogWithConfigEnabled
TableMetadata.newTableMetadata(
new Schema(List.of(Types.NestedField.of(1, false, "col1", new Types.StringType()))),
PartitionSpec.unpartitioned(),
"file:///tmp/ns1/my_table",
externalCatalogBase + "/ns1/my_table",
Map.of());
try (ResolvingFileIO resolvingFileIO = new ResolvingFileIO()) {
resolvingFileIO.initialize(Map.of());
resolvingFileIO.setConf(new Configuration());
String fileLocation = "file:///tmp/ns1/my_table/metadata/v1.metadata.json";
String fileLocation = externalCatalogBase + "/ns1/my_table/metadata/v1.metadata.json";
TableMetadataParser.write(tableMetadata, resolvingFileIO.newOutputFile(fileLocation));
restCatalog.registerTable(TableIdentifier.of(ns1, "my_table"), fileLocation);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.core.Response;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Path;
import java.time.Instant;
import java.util.List;
Expand All @@ -41,6 +42,7 @@
import org.apache.polaris.core.admin.model.StorageConfigInfo;
import org.apache.polaris.service.it.env.CatalogApi;
import org.apache.polaris.service.it.env.ClientCredentials;
import org.apache.polaris.service.it.env.IntegrationTestsHelper;
import org.apache.polaris.service.it.env.ManagementApi;
import org.apache.polaris.service.it.env.PolarisApiEndpoints;
import org.apache.polaris.service.it.env.PolarisClient;
Expand Down Expand Up @@ -82,7 +84,7 @@ public class PolarisSparkIntegrationTest {
private String catalogName;
private String externalCatalogName;

@TempDir public Path warehouseDir;
private URI warehouseDir;

@BeforeAll
public static void setup() throws IOException {
Expand All @@ -95,13 +97,16 @@ public static void cleanup() {
}

@BeforeEach
public void before(PolarisApiEndpoints apiEndpoints, ClientCredentials credentials) {
public void before(
PolarisApiEndpoints apiEndpoints, ClientCredentials credentials, @TempDir Path tempDir) {
endpoints = apiEndpoints;
client = polarisClient(endpoints);
sparkToken = client.obtainToken(credentials);
managementApi = client.managementApi(credentials);
catalogApi = client.catalogApi(credentials);

warehouseDir = IntegrationTestsHelper.getTemporaryDirectory(tempDir).resolve("spark-warehouse");

catalogName = client.newEntityName("spark_catalog");
externalCatalogName = client.newEntityName("spark_ext_catalog");

Expand Down
Loading