diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index 4fc33d96c2..c1c0554242 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -46,7 +46,8 @@ dependencies { api(project(":polaris-jpa-model")) api(project(":polaris-quarkus-admin")) - api(project(":polaris-quarkus-test-commons")) + api(project(":polaris-quarkus-common")) + api(project(":polaris-quarkus-test-common")) api(project(":polaris-quarkus-defaults")) api(project(":polaris-quarkus-server")) api(project(":polaris-quarkus-service")) diff --git a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatasourceOperations.java b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatasourceOperations.java index 6fec8e67fe..5ef1455bec 100644 --- a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatasourceOperations.java +++ b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/DatasourceOperations.java @@ -38,7 +38,8 @@ public class DatasourceOperations { - private static final String CONSTRAINT_VIOLATION_SQL_CODE = "23505"; + private static final String CONSTRAINT_VIOLATION_SQL_CODE_POSTGRES = "23505"; + private static final String TABLE_DOES_NOT_EXIST_SQL_CODE_POSTGRES = "42P01"; private final DataSource datasource; @@ -182,7 +183,11 @@ public interface TransactionCallback { } public boolean isConstraintViolation(SQLException e) { - return CONSTRAINT_VIOLATION_SQL_CODE.equals(e.getSQLState()); + return CONSTRAINT_VIOLATION_SQL_CODE_POSTGRES.equals(e.getSQLState()); + } + + public boolean isTableNotExists(SQLException e) { + return TABLE_DOES_NOT_EXIST_SQL_CODE_POSTGRES.equals(e.getSQLState()); } private Connection borrowConnection() throws SQLException { diff --git a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcBasePersistenceImpl.java b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcBasePersistenceImpl.java index 5ffce813f9..457c1325a9 100644 --- a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcBasePersistenceImpl.java +++ b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcBasePersistenceImpl.java @@ -315,6 +315,12 @@ private PolarisBaseEntity getPolarisBaseEntity(String query) { return results.getFirst(); } } catch (SQLException e) { + // This look-up is used for checking if the realm is bootstrap or not. + // If we have 1 DB per realm it might happen that the realm is not boostrap + // at all. + if (datasourceOperations.isTableNotExists(e)) { + return null; + } throw new RuntimeException( String.format("Failed to retrieve polaris entity due to %s", e.getMessage()), e); } diff --git a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java index f19194f33d..956f6953c7 100644 --- a/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java +++ b/extension/persistence/relational-jdbc/src/main/java/org/apache/polaris/extension/persistence/relational/jdbc/JdbcMetaStoreManagerFactory.java @@ -21,7 +21,6 @@ import io.smallrye.common.annotation.Identifier; import jakarta.annotation.Nullable; import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import java.sql.Connection; import java.sql.SQLException; @@ -41,6 +40,7 @@ import org.apache.polaris.core.entity.PolarisPrincipalSecrets; import org.apache.polaris.core.persistence.AtomicOperationMetaStoreManager; import org.apache.polaris.core.persistence.BasePersistence; +import org.apache.polaris.core.persistence.DatasourceSupplier; import org.apache.polaris.core.persistence.MetaStoreManagerFactory; import org.apache.polaris.core.persistence.PolarisMetaStoreManager; import org.apache.polaris.core.persistence.PrincipalSecretsGenerator; @@ -73,7 +73,7 @@ public class JdbcMetaStoreManagerFactory implements MetaStoreManagerFactory { protected final PolarisDiagnostics diagServices = new PolarisDefaultDiagServiceImpl(); @Inject PolarisStorageIntegrationProvider storageIntegrationProvider; - @Inject Instance dataSource; + @Inject DatasourceSupplier jdbcDatasource; protected JdbcMetaStoreManagerFactory() {} @@ -93,7 +93,8 @@ protected PolarisMetaStoreManager createNewMetaStoreManager() { private void initializeForRealm( RealmContext realmContext, RootCredentialsSet rootCredentialsSet, boolean isBootstrap) { - DatasourceOperations databaseOperations = getDatasourceOperations(isBootstrap); + DatasourceOperations databaseOperations = + getDatasourceOperations(isBootstrap, realmContext.getRealmIdentifier()); sessionSupplierMap.put( realmContext.getRealmIdentifier(), () -> @@ -107,12 +108,13 @@ private void initializeForRealm( metaStoreManagerMap.put(realmContext.getRealmIdentifier(), metaStoreManager); } - private DatasourceOperations getDatasourceOperations(boolean isBootstrap) { - DatasourceOperations databaseOperations = new DatasourceOperations(dataSource.get()); + private DatasourceOperations getDatasourceOperations(boolean isBootstrap, String realmId) { + DataSource datasource = jdbcDatasource.fromRealmId(realmId); + DatasourceOperations databaseOperations = new DatasourceOperations(datasource); if (isBootstrap) { try { DatabaseType databaseType; - try (Connection connection = dataSource.get().getConnection()) { + try (Connection connection = datasource.getConnection()) { String productName = connection.getMetaData().getDatabaseProductName(); databaseType = DatabaseType.fromDisplayName(productName); } diff --git a/gradle/projects.main.properties b/gradle/projects.main.properties index 6161eee47b..e75ee28aca 100644 --- a/gradle/projects.main.properties +++ b/gradle/projects.main.properties @@ -30,7 +30,8 @@ polaris-quarkus-service=quarkus/service polaris-quarkus-server=quarkus/server polaris-quarkus-spark-tests=quarkus/spark-tests polaris-quarkus-admin=quarkus/admin -polaris-quarkus-test-commons=quarkus/test-commons +polaris-quarkus-common=quarkus/common +polaris-quarkus-test-common=quarkus/test-common polaris-quarkus-run-script=quarkus/run-script polaris-eclipselink=extension/persistence/eclipselink polaris-jpa-model=extension/persistence/jpa-model diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/DatasourceSupplier.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/DatasourceSupplier.java new file mode 100644 index 0000000000..7daa3a6a9c --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/DatasourceSupplier.java @@ -0,0 +1,25 @@ +/* + * 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.core.persistence; + +import javax.sql.DataSource; + +public interface DatasourceSupplier { + DataSource fromRealmId(String realmId); +} diff --git a/quarkus/admin/build.gradle.kts b/quarkus/admin/build.gradle.kts index 7b19a132a7..fd94d96316 100644 --- a/quarkus/admin/build.gradle.kts +++ b/quarkus/admin/build.gradle.kts @@ -46,7 +46,6 @@ dependencies { runtimeOnly(project(":polaris-eclipselink")) runtimeOnly(project(":polaris-relational-jdbc")) runtimeOnly("org.postgresql:postgresql") - implementation("io.quarkus:quarkus-jdbc-postgresql") implementation(enforcedPlatform(libs.quarkus.bom)) implementation("io.quarkus:quarkus-picocli") @@ -54,7 +53,8 @@ dependencies { implementation("org.jboss.slf4j:slf4j-jboss-logmanager") - testImplementation(project(":polaris-quarkus-test-commons")) + implementation(project(":polaris-quarkus-common")) + testImplementation(project(":polaris-quarkus-test-common")) testFixturesApi(project(":polaris-core")) testFixturesApi(enforcedPlatform(libs.quarkus.bom)) diff --git a/quarkus/admin/src/main/resources/application.properties b/quarkus/admin/src/main/resources/application.properties index 6665be818d..e5c4c5856f 100644 --- a/quarkus/admin/src/main/resources/application.properties +++ b/quarkus/admin/src/main/resources/application.properties @@ -50,3 +50,21 @@ quarkus.index-dependency.guava.artifact-id=guava quarkus.index-dependency.protobuf.group-id=com.google.protobuf quarkus.index-dependency.protobuf.artifact-id=protobuf-java quarkus.datasource.devservices.image-name=postgres:17-alpine + +#quarkus.datasource.db-kind=pgsql +#quarkus.datasource.jdbc.url=polaris +#quarkus.datasource.username=polaris +#quarkus.datasource.password=polaris +quarkus.datasource.\"realm1_ds\".db-kind=pgsql +quarkus.datasource.\"realm1_ds\".jdbc.url=polaris +quarkus.datasource.\"realm1_ds\".username=polaris +quarkus.datasource.\"realm1_ds\".password=polaris +quarkus.datasource.\"realm2_ds\".db-kind=pgsql +quarkus.datasource.\"realm2_ds\".jdbc.url=polaris +quarkus.datasource.\"realm2_ds\".username=polaris +quarkus.datasource.\"realm2_ds\".password=polaris +quarkus.datasource.\"realm3_ds\".db-kind=pgsql +quarkus.datasource.\"realm3_ds\".jdbc.url=polaris +quarkus.datasource.\"realm3_ds\".username=polaris +quarkus.datasource.\"realm3_ds\".password=polaris + diff --git a/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java b/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java index a64002983d..6eec8b0db9 100644 --- a/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java +++ b/quarkus/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java @@ -22,8 +22,8 @@ import java.util.List; import java.util.Map; -import org.apache.polaris.test.commons.PostgresRelationalJdbcLifeCycleManagement; -import org.apache.polaris.test.commons.RelationalJdbcProfile; +import org.apache.polaris.test.common.PostgresRelationalJdbcLifeCycleManagement; +import org.apache.polaris.test.common.RelationalJdbcProfile; public class RelationalJdbcAdminProfile extends RelationalJdbcProfile { @Override @@ -36,6 +36,10 @@ public List testResources() { return List.of( new TestResourceEntry( PostgresRelationalJdbcLifeCycleManagement.class, - Map.of(INIT_SCRIPT, "org/apache/polaris/admintool/init.sql"))); + Map.of( + INIT_SCRIPT, + "org/apache/polaris/admintool/jdbc/init.sql", + "databases", + "realm1,realm2,realm3"))); } } diff --git a/quarkus/admin/src/testFixtures/resources/org/apache/polaris/admintool/jdbc/init.sql b/quarkus/admin/src/testFixtures/resources/org/apache/polaris/admintool/jdbc/init.sql new file mode 100644 index 0000000000..a6037243b1 --- /dev/null +++ b/quarkus/admin/src/testFixtures/resources/org/apache/polaris/admintool/jdbc/init.sql @@ -0,0 +1,30 @@ +/* + * 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. + */ + +-- Create two more databases for testing. The first database, polaris_realm1, is created +-- during container initialization. See PostgresTestResourceLifecycleManager. + +-- Note: the database names must follow the pattern polaris_{realm}. That's the pattern +-- specified by the persistence.xml file used in tests. + +CREATE DATABASE realm2; +GRANT ALL PRIVILEGES ON DATABASE realm2 TO polaris; + +CREATE DATABASE realm3; +GRANT ALL PRIVILEGES ON DATABASE realm3 TO polaris; diff --git a/quarkus/common/build.gradle.kts b/quarkus/common/build.gradle.kts new file mode 100644 index 0000000000..d6855b9796 --- /dev/null +++ b/quarkus/common/build.gradle.kts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +plugins { + alias(libs.plugins.jandex) + id("java-test-fixtures") +} + +configurations.all { + exclude(group = "org.antlr", module = "antlr4-runtime") + exclude(group = "org.scala-lang", module = "scala-library") + exclude(group = "org.scala-lang", module = "scala-reflect") +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +dependencies { + implementation(project(":polaris-core")) + implementation(project(":polaris-relational-jdbc")) + + compileOnly(libs.smallrye.config.core) // @ConfigMap + implementation(enforcedPlatform(libs.quarkus.bom)) + implementation("io.quarkus:quarkus-arc") +} diff --git a/quarkus/common/src/main/java/org/apache/polaris/common/QuarkusDatasourceSupplier.java b/quarkus/common/src/main/java/org/apache/polaris/common/QuarkusDatasourceSupplier.java new file mode 100644 index 0000000000..11c5952218 --- /dev/null +++ b/quarkus/common/src/main/java/org/apache/polaris/common/QuarkusDatasourceSupplier.java @@ -0,0 +1,71 @@ +/* + * 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.common; + +import io.quarkus.arc.All; +import io.quarkus.arc.InstanceHandle; +import java.util.List; +import javax.sql.DataSource; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.apache.polaris.core.persistence.DatasourceSupplier; + +@ApplicationScoped +public class QuarkusDatasourceSupplier implements DatasourceSupplier { + private final List> dataSources; + private final RelationalJdbcConfiguration relationalJdbcConfiguration; + + private static final String DEFAULT_DATA_SOURCE_NAME = "default"; + + @Inject + public QuarkusDatasourceSupplier( + RelationalJdbcConfiguration relationalJdbcConfiguration, + @All List> dataSources) { + this.relationalJdbcConfiguration = relationalJdbcConfiguration; + this.dataSources = dataSources; + } + + @Override + public DataSource fromRealmId(String realmId) { + // check if the mapping of realm to DS exists, otherwise fall back to default + String dataSourceName = relationalJdbcConfiguration.realms().getOrDefault( + realmId, + relationalJdbcConfiguration.defaultDatasource().orElse(null) + ); + + // if neither mapping exists nor default DS exists, fail + if (dataSourceName == null) { + throw new IllegalStateException(String.format( + "No datasource configured with name: %s nor default datasource configured", realmId)); + } + + // check if there is actually a datasource of that dataSourceName + return dataSources.stream() + .filter(ds -> { + String name = ds.getBean().getName(); + name = name == null ? DEFAULT_DATA_SOURCE_NAME : name; + return name.equals(dataSourceName); + }) + .map(InstanceHandle::get) + .findFirst() + .orElseThrow(() -> new IllegalStateException(String.format( + "No datasource configured with name: %s", dataSourceName))); + } +} diff --git a/quarkus/common/src/main/java/org/apache/polaris/common/RelationalJdbcConfiguration.java b/quarkus/common/src/main/java/org/apache/polaris/common/RelationalJdbcConfiguration.java new file mode 100644 index 0000000000..f07fbaa65a --- /dev/null +++ b/quarkus/common/src/main/java/org/apache/polaris/common/RelationalJdbcConfiguration.java @@ -0,0 +1,38 @@ +/* + * 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.common; + +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithParentName; + +import java.util.Map; +import java.util.Optional; + +@ConfigMapping(prefix = "polaris.relational.jdbc.datasource") +public interface RelationalJdbcConfiguration { + /** realmId to configured Datasource name mapping. */ + @WithParentName + Map realms(); + + /** + * Default datasource name to be used for a realmId when there is no mapping of realmId to + * Datasource name present. + */ + Optional defaultDatasource(); +} diff --git a/quarkus/defaults/src/main/resources/application-it.properties b/quarkus/defaults/src/main/resources/application-it.properties index 4419d4d590..4351694a19 100644 --- a/quarkus/defaults/src/main/resources/application-it.properties +++ b/quarkus/defaults/src/main/resources/application-it.properties @@ -46,4 +46,7 @@ polaris.realm-context.realms=POLARIS,OTHER polaris.storage.gcp.token=token polaris.storage.gcp.lifespan=PT1H - +quarkus.datasource.realm1_ds.db-kind=pgsql +quarkus.datasource.realm1_ds.jdbc.url=polaris +quarkus.datasource.realm1_ds.username=polaris +quarkus.datasource.realm1_ds.password=polaris diff --git a/quarkus/defaults/src/main/resources/application.properties b/quarkus/defaults/src/main/resources/application.properties index c7676b2ba0..f344e8352b 100644 --- a/quarkus/defaults/src/main/resources/application.properties +++ b/quarkus/defaults/src/main/resources/application.properties @@ -173,3 +173,8 @@ quarkus.index-dependency.protobuf.artifact-id=protobuf-java # force the locale, just in case the system's using another default locale quarkus.default-locale=en_US +# TODO: remove this, its there to make the custom ds work. +quarkus.datasource.realm1_ds.db-kind=pgsql +quarkus.datasource.realm1_ds.jdbc.url=polaris +quarkus.datasource.realm1_ds.username=polaris +quarkus.datasource.realm1_ds.password=polaris diff --git a/quarkus/service/build.gradle.kts b/quarkus/service/build.gradle.kts index 97b3daa0de..7258ed1c6d 100644 --- a/quarkus/service/build.gradle.kts +++ b/quarkus/service/build.gradle.kts @@ -51,6 +51,11 @@ dependencies { implementation("io.quarkus:quarkus-security") implementation("io.quarkus:quarkus-smallrye-context-propagation") implementation("io.quarkus:quarkus-smallrye-fault-tolerance") + runtimeOnly("io.quarkus:quarkus-jdbc-postgresql") { + exclude(group = "org.antlr", module = "antlr4-runtime") + exclude(group = "org.scala-lang", module = "scala-library") + exclude(group = "org.scala-lang", module = "scala-reflect") + } implementation(libs.jakarta.enterprise.cdi.api) implementation(libs.jakarta.inject.api) @@ -107,13 +112,7 @@ dependencies { testImplementation("software.amazon.awssdk:glue") testImplementation("software.amazon.awssdk:kms") testImplementation("software.amazon.awssdk:dynamodb") - - runtimeOnly(project(":polaris-relational-jdbc")) - runtimeOnly("io.quarkus:quarkus-jdbc-postgresql") { - exclude(group = "org.antlr", module = "antlr4-runtime") - exclude(group = "org.scala-lang", module = "scala-library") - exclude(group = "org.scala-lang", module = "scala-reflect") - } + testImplementation(project(":polaris-relational-jdbc")) testImplementation(platform(libs.quarkus.bom)) testImplementation("io.quarkus:quarkus-junit5") testImplementation("io.quarkus:quarkus-junit5-mockito") @@ -124,7 +123,8 @@ dependencies { testImplementation(libs.threeten.extra) testImplementation(libs.hawkular.agent.prometheus.scraper) - testImplementation(project(":polaris-quarkus-test-commons")) + implementation(project(":polaris-quarkus-common")) + testImplementation(project(":polaris-quarkus-test-common")) testImplementation("io.quarkus:quarkus-junit5") testImplementation(platform(libs.testcontainers.bom)) testImplementation("org.testcontainers:testcontainers") diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusApplicationIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusApplicationIT.java index dd718db732..1298061f9e 100644 --- a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusApplicationIT.java +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusApplicationIT.java @@ -21,7 +21,7 @@ import io.quarkus.test.junit.QuarkusIntegrationTest; import io.quarkus.test.junit.TestProfile; import org.apache.polaris.service.it.test.PolarisApplicationIntegrationTest; -import org.apache.polaris.test.commons.RelationalJdbcProfile; +import org.apache.polaris.test.common.RelationalJdbcProfile; @TestProfile(RelationalJdbcProfile.class) @QuarkusIntegrationTest diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusManagementServiceIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusManagementServiceIT.java index 0961889fd6..ec29d4db3d 100644 --- a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusManagementServiceIT.java +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusManagementServiceIT.java @@ -21,7 +21,7 @@ import io.quarkus.test.junit.QuarkusIntegrationTest; import io.quarkus.test.junit.TestProfile; import org.apache.polaris.service.it.test.PolarisManagementServiceIntegrationTest; -import org.apache.polaris.test.commons.RelationalJdbcProfile; +import org.apache.polaris.test.common.RelationalJdbcProfile; @TestProfile(RelationalJdbcProfile.class) @QuarkusIntegrationTest diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusPolicyServiceIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusPolicyServiceIT.java index 5907fe5515..4891f1654e 100644 --- a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusPolicyServiceIT.java +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusPolicyServiceIT.java @@ -21,7 +21,7 @@ import io.quarkus.test.junit.QuarkusIntegrationTest; import io.quarkus.test.junit.TestProfile; import org.apache.polaris.service.it.test.PolarisPolicyServiceIntegrationTest; -import org.apache.polaris.test.commons.RelationalJdbcProfile; +import org.apache.polaris.test.common.RelationalJdbcProfile; @TestProfile(RelationalJdbcProfile.class) @QuarkusIntegrationTest diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusViewFileIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusViewFileIT.java index 7471032a52..e39b65190a 100644 --- a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusViewFileIT.java +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcQuarkusViewFileIT.java @@ -21,7 +21,7 @@ import io.quarkus.test.junit.QuarkusIntegrationTest; import io.quarkus.test.junit.TestProfile; import org.apache.polaris.service.it.test.PolarisRestCatalogViewFileIntegrationTest; -import org.apache.polaris.test.commons.RelationalJdbcProfile; +import org.apache.polaris.test.common.RelationalJdbcProfile; @TestProfile(RelationalJdbcProfile.class) @QuarkusIntegrationTest diff --git a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java index 59b35fe912..9a03540940 100644 --- a/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java +++ b/quarkus/service/src/intTest/java/org/apache/polaris/service/quarkus/it/relational/jdbc/JdbcRestCatalogIT.java @@ -21,7 +21,7 @@ import io.quarkus.test.junit.QuarkusIntegrationTest; import io.quarkus.test.junit.TestProfile; import org.apache.polaris.service.it.test.PolarisRestCatalogIntegrationTest; -import org.apache.polaris.test.commons.RelationalJdbcProfile; +import org.apache.polaris.test.common.RelationalJdbcProfile; @TestProfile(RelationalJdbcProfile.class) @QuarkusIntegrationTest diff --git a/quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java b/quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java index 625e57e45d..5ecddc65f8 100644 --- a/quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java +++ b/quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java @@ -41,10 +41,7 @@ import org.apache.polaris.core.config.PolarisConfigurationStore; import org.apache.polaris.core.context.CallContext; import org.apache.polaris.core.context.RealmContext; -import org.apache.polaris.core.persistence.BasePersistence; -import org.apache.polaris.core.persistence.MetaStoreManagerFactory; -import org.apache.polaris.core.persistence.PolarisEntityManager; -import org.apache.polaris.core.persistence.PolarisMetaStoreManager; +import org.apache.polaris.core.persistence.*; import org.apache.polaris.core.persistence.bootstrap.RootCredentialsSet; import org.apache.polaris.core.secrets.UserSecretsManager; import org.apache.polaris.core.secrets.UserSecretsManagerFactory; @@ -258,6 +255,13 @@ public ActiveRolesProvider activeRolesProvider( return activeRolesProviders.select(Identifier.Literal.of(persistenceType)).get(); } + // @Produces + // public DatasourceSupplier datasourceSupplier( + // @Any RelationalJdbcConfiguration relationalJdbcConfiguration, + // @All List> datasources) { + // return new QuarkusDatasourceSupplier(relationalJdbcConfiguration, datasources); + // } + public void closeTaskExecutor(@Disposes @Identifier("task-executor") ManagedExecutor executor) { executor.close(); } diff --git a/quarkus/test-commons/build.gradle.kts b/quarkus/test-common/build.gradle.kts similarity index 100% rename from quarkus/test-commons/build.gradle.kts rename to quarkus/test-common/build.gradle.kts diff --git a/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/PostgresRelationalJdbcLifeCycleManagement.java b/quarkus/test-common/src/main/java/org/apache/polaris/test/common/PostgresRelationalJdbcLifeCycleManagement.java similarity index 50% rename from quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/PostgresRelationalJdbcLifeCycleManagement.java rename to quarkus/test-common/src/main/java/org/apache/polaris/test/common/PostgresRelationalJdbcLifeCycleManagement.java index 9dc230722f..3e764aaa24 100644 --- a/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/PostgresRelationalJdbcLifeCycleManagement.java +++ b/quarkus/test-common/src/main/java/org/apache/polaris/test/common/PostgresRelationalJdbcLifeCycleManagement.java @@ -16,11 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - -package org.apache.polaris.test.commons; +package org.apache.polaris.test.common; import io.quarkus.test.common.DevServicesContext; import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Map; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @@ -28,14 +31,18 @@ public class PostgresRelationalJdbcLifeCycleManagement implements QuarkusTestResourceLifecycleManager, DevServicesContext.ContextAware { public static final String INIT_SCRIPT = "init-script"; + public static final String DATABASES = "databases"; private PostgreSQLContainer postgres; private String initScript; + private List databases; private DevServicesContext context; @Override public void init(Map initArgs) { initScript = initArgs.get(INIT_SCRIPT); + String databases = initArgs.get(DATABASES); + this.databases = databases == null ? new ArrayList<>() : Arrays.asList(databases.split(",")); } @Override @@ -43,7 +50,7 @@ public void init(Map initArgs) { public Map start() { postgres = new PostgreSQLContainer<>(DockerImageName.parse("postgres:17-alpine")) - .withDatabaseName("polaris_db") + .withDatabaseName("realm1") .withUsername("polaris") .withPassword("polaris"); @@ -53,19 +60,46 @@ public Map start() { context.containerNetworkId().ifPresent(postgres::withNetworkMode); postgres.start(); - return Map.of( - "polaris.persistence.type", - "relational-jdbc", - "quarkus.datasource.db-kind", - "pgsql", - "quarkus.datasource.jdbc.url", - postgres.getJdbcUrl(), - "quarkus.datasource.username", - postgres.getUsername(), - "quarkus.datasource.password", - postgres.getPassword(), - "quarkus.datasource.jdbc.initial-size", - "10"); + + if (databases.isEmpty()) { + Map props = generateDataSourceProps(List.of("realm1")); + // make realm1_ds as the default ds + props.put("polaris.relational.jdbc.datasource.default-datasource", "realm1_ds"); + return props; + } else { + Map allProps = new HashMap<>(); + allProps.putAll(generateDataSourceMappingProps(databases)); + allProps.putAll(generateDataSourceProps(databases)); + return allProps; + } + } + + private Map generateDataSourceProps(List dataSources) { + Map props = new HashMap<>(); + props.put("polaris.persistence.type", "relational-jdbc"); + for (String database : dataSources) { + props.put(String.format("quarkus.datasource.%s.db-kind", database + "_ds"), "pgsql"); + props.put(String.format("quarkus.datasource.%s.active", database + "_ds"), "true"); + props.put( + String.format("quarkus.datasource.%s.jdbc.url", database + "_ds"), + postgres.getJdbcUrl().replace("realm1", database)); + props.put( + String.format("quarkus.datasource.%s.username", database + "_ds"), + postgres.getUsername()); + props.put( + String.format("quarkus.datasource.%s.password", database + "_ds"), + postgres.getPassword()); + } + return props; + } + + private Map generateDataSourceMappingProps(List realms) { + Map props = new HashMap<>(); + // polaris.relation.jdbc.datasource.realm=realm_ds + for (String database : realms) { + props.put(String.format("polaris.relational.jdbc.datasource.%s", database), database + "_ds"); + } + return props; } @Override diff --git a/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/RelationalJdbcProfile.java b/quarkus/test-common/src/main/java/org/apache/polaris/test/common/RelationalJdbcProfile.java similarity index 97% rename from quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/RelationalJdbcProfile.java rename to quarkus/test-common/src/main/java/org/apache/polaris/test/common/RelationalJdbcProfile.java index 38f7bd61a0..fa48a80bd6 100644 --- a/quarkus/test-commons/src/main/java/org/apache/polaris/test/commons/RelationalJdbcProfile.java +++ b/quarkus/test-common/src/main/java/org/apache/polaris/test/common/RelationalJdbcProfile.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.polaris.test.commons; +package org.apache.polaris.test.common; import io.quarkus.test.junit.QuarkusTestProfile; import java.util.List;