diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/ManagementServiceTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/ManagementServiceTest.java index ff42c384a7..181edd62e3 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/ManagementServiceTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/ManagementServiceTest.java @@ -51,7 +51,6 @@ import org.apache.polaris.core.secrets.UnsafeInMemorySecretsManager; import org.apache.polaris.service.TestServices; import org.apache.polaris.service.admin.PolarisAdminService; -import org.apache.polaris.service.config.DefaultConfigurationStore; import org.apache.polaris.service.config.ReservedProperties; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -220,7 +219,7 @@ public String getAuthenticationScheme() { return ""; } }, - new PolarisAuthorizerImpl(new DefaultConfigurationStore(Map.of())), + new PolarisAuthorizerImpl(services.configurationStore()), new ReservedProperties() { @Override public List prefixes() { diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java index d3a2b0dba2..9bec65ab49 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java @@ -26,7 +26,6 @@ import io.quarkus.test.junit.QuarkusMock; import io.quarkus.test.junit.QuarkusTestProfile; import jakarta.annotation.Nonnull; -import jakarta.annotation.Nullable; import jakarta.enterprise.context.RequestScoped; import jakarta.enterprise.inject.Alternative; import jakarta.inject.Inject; @@ -56,7 +55,6 @@ import org.apache.polaris.core.auth.AuthenticatedPolarisPrincipal; import org.apache.polaris.core.auth.PolarisAuthorizer; import org.apache.polaris.core.auth.PolarisAuthorizerImpl; -import org.apache.polaris.core.config.FeatureConfiguration; import org.apache.polaris.core.config.PolarisConfigurationStore; import org.apache.polaris.core.context.CallContext; import org.apache.polaris.core.context.RealmContext; @@ -85,7 +83,6 @@ import org.apache.polaris.service.catalog.iceberg.IcebergCatalog; import org.apache.polaris.service.catalog.io.FileIOFactory; import org.apache.polaris.service.catalog.policy.PolicyCatalog; -import org.apache.polaris.service.config.DefaultConfigurationStore; import org.apache.polaris.service.config.RealmEntityManagerFactory; import org.apache.polaris.service.config.ReservedProperties; import org.apache.polaris.service.context.catalog.CallContextCatalogFactory; @@ -123,6 +120,10 @@ public Map getConfigOverrides() { "polaris.features.\"SUPPORTED_CATALOG_STORAGE_TYPES\"", "[\"FILE\",\"S3\"]", "polaris.readiness.ignore-severe-issues", + "true", + "polaris.features.\"ENABLE_GENERIC_TABLES\"", + "true", + "polaris.features.\"ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING\"", "true"); } } @@ -183,12 +184,6 @@ public Map getConfigOverrides() { new Schema( required(3, "id", Types.IntegerType.get(), "unique ID 🤪"), required(4, "data", Types.StringType.get())); - protected final PolarisAuthorizer polarisAuthorizer = - new PolarisAuthorizerImpl( - new DefaultConfigurationStore( - Map.of( - FeatureConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING.key, - true))); protected final ReservedProperties reservedProperties = ReservedProperties.NONE; @Inject protected MetaStoreManagerFactory managerFactory; @@ -200,6 +195,7 @@ public Map getConfigOverrides() { @Inject protected FileIOFactory fileIOFactory; @Inject protected PolarisEventListener polarisEventListener; @Inject protected CatalogHandlerUtils catalogHandlerUtils; + @Inject protected PolarisConfigurationStore configurationStore; protected IcebergCatalog baseCatalog; protected PolarisGenericTableCatalog genericTableCatalog; @@ -213,6 +209,7 @@ public Map getConfigOverrides() { protected PrincipalEntity principalEntity; protected CallContext callContext; protected AuthenticatedPolarisPrincipal authenticatedRoot; + protected PolarisAuthorizer polarisAuthorizer; private PolarisCallContext polarisContext; @@ -227,33 +224,17 @@ public static void setUpMocks() { @BeforeEach public void before(TestInfo testInfo) { RealmContext realmContext = testInfo::getDisplayName; + QuarkusMock.installMockForType(realmContext, RealmContext.class); metaStoreManager = managerFactory.getOrCreateMetaStoreManager(realmContext); userSecretsManager = userSecretsManagerFactory.getOrCreateUserSecretsManager(realmContext); - Map configMap = - Map.of( - "ALLOW_SPECIFYING_FILE_IO_IMPL", - true, - "ALLOW_INSECURE_STORAGE_TYPES", - true, - "ALLOW_EXTERNAL_METADATA_FILE_LOCATION", - true, - "SUPPORTED_CATALOG_STORAGE_TYPES", - List.of("FILE", "S3"), - "ENABLE_GENERIC_TABLES", - true); + polarisAuthorizer = new PolarisAuthorizerImpl(configurationStore); + polarisContext = new PolarisCallContext( managerFactory.getOrCreateSessionSupplier(realmContext).get(), diagServices, - new PolarisConfigurationStore() { - @Override - public @Nullable T getConfiguration(PolarisCallContext ctx, String configName) { - @SuppressWarnings("unchecked") - var r = (T) configMap.get(configName); - return r; - } - }, + configurationStore, clock); this.entityManager = realmEntityManagerFactory.getOrCreateEntityManager(realmContext); diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTRSAKeyPairTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTRSAKeyPairTest.java index 84ca59926b..a7dcc10a8f 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTRSAKeyPairTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTRSAKeyPairTest.java @@ -24,12 +24,14 @@ import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; import java.nio.file.Files; import java.nio.file.Path; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; -import java.util.HashMap; import org.apache.polaris.core.PolarisCallContext; +import org.apache.polaris.core.config.PolarisConfigurationStore; import org.apache.polaris.core.entity.PolarisBaseEntity; import org.apache.polaris.core.entity.PolarisEntitySubType; import org.apache.polaris.core.entity.PolarisEntityType; @@ -43,13 +45,15 @@ import org.apache.polaris.service.auth.TokenBroker; import org.apache.polaris.service.auth.TokenRequestValidator; import org.apache.polaris.service.auth.TokenResponse; -import org.apache.polaris.service.config.DefaultConfigurationStore; import org.apache.polaris.service.types.TokenType; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +@QuarkusTest public class JWTRSAKeyPairTest { + @Inject protected PolarisConfigurationStore configurationStore; + @Test public void testSuccessfulTokenGeneration() throws Exception { Path privateFileLocation = Files.createTempFile("test-private", ".pem"); @@ -59,8 +63,8 @@ public void testSuccessfulTokenGeneration() throws Exception { final String clientId = "test-client-id"; final String scope = "PRINCIPAL_ROLE:TEST"; - DefaultConfigurationStore store = new DefaultConfigurationStore(new HashMap<>()); - PolarisCallContext polarisCallContext = new PolarisCallContext(null, null, store, null); + PolarisCallContext polarisCallContext = + new PolarisCallContext(null, null, configurationStore, null); PolarisMetaStoreManager metastoreManager = Mockito.mock(PolarisMetaStoreManager.class); String mainSecret = "client-secret"; PolarisPrincipalSecrets principalSecrets = diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/GetConfigTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/GetConfigTest.java index c497cee6a6..858edb1fa9 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/GetConfigTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/GetConfigTest.java @@ -21,7 +21,6 @@ import static jakarta.ws.rs.core.Response.Status.CREATED; import static org.assertj.core.api.Assertions.assertThat; -import io.quarkus.test.junit.QuarkusTest; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.Map; @@ -33,7 +32,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -@QuarkusTest public class GetConfigTest { @ParameterizedTest @ValueSource(booleans = {true, false}) diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java index 3bd8f45aaf..6d77a3459a 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java @@ -246,6 +246,7 @@ public void before(TestInfo testInfo) { .formatted( testInfo.getTestMethod().map(Method::getName).orElse("test"), System.nanoTime()); RealmContext realmContext = () -> realmName; + QuarkusMock.installMockForType(realmContext, RealmContext.class); metaStoreManager = managerFactory.getOrCreateMetaStoreManager(realmContext); userSecretsManager = userSecretsManagerFactory.getOrCreateUserSecretsManager(realmContext); polarisContext = @@ -254,6 +255,7 @@ public void before(TestInfo testInfo) { diagServices, configurationStore, Clock.systemDefaultZone()); + entityManager = new PolarisEntityManager( metaStoreManager, new StorageCredentialCache(), createEntityCache(metaStoreManager)); diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogViewTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogViewTest.java index 0ac72a1b51..70fe9304bb 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogViewTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogViewTest.java @@ -166,6 +166,7 @@ public void before(TestInfo testInfo) { .formatted( testInfo.getTestMethod().map(Method::getName).orElse("test"), System.nanoTime()); RealmContext realmContext = () -> realmName; + QuarkusMock.installMockForType(realmContext, RealmContext.class); metaStoreManager = managerFactory.getOrCreateMetaStoreManager(realmContext); userSecretsManager = userSecretsManagerFactory.getOrCreateUserSecretsManager(realmContext); diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogHandlerAuthzTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogHandlerAuthzTest.java index 0f9fd31903..6deb37bb3e 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogHandlerAuthzTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogHandlerAuthzTest.java @@ -19,6 +19,7 @@ package org.apache.polaris.service.quarkus.catalog; import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; import java.util.List; import java.util.Map; import java.util.Set; @@ -31,6 +32,7 @@ import org.junit.jupiter.api.Test; @QuarkusTest +@TestProfile(PolarisAuthzTestBase.Profile.class) public class PolarisGenericTableCatalogHandlerAuthzTest extends PolarisAuthzTestBase { private GenericTableCatalogHandler newWrapper() { diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogTest.java index 267fbb3867..c5c5755fd8 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogTest.java @@ -168,6 +168,7 @@ public void before(TestInfo testInfo) { .formatted( testInfo.getTestMethod().map(Method::getName).orElse("test"), System.nanoTime()); RealmContext realmContext = () -> realmName; + QuarkusMock.installMockForType(realmContext, RealmContext.class); metaStoreManager = managerFactory.getOrCreateMetaStoreManager(realmContext); userSecretsManager = userSecretsManagerFactory.getOrCreateUserSecretsManager(realmContext); polarisContext = diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java index c2aea07e3b..e4505ebe51 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java @@ -19,6 +19,7 @@ package org.apache.polaris.service.quarkus.catalog; import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; import java.util.Arrays; import java.util.List; import java.util.Set; @@ -38,6 +39,7 @@ import org.junit.jupiter.api.Test; @QuarkusTest +@TestProfile(PolarisAuthzTestBase.Profile.class) public class PolicyCatalogHandlerAuthzTest extends PolarisAuthzTestBase { private PolicyCatalogHandler newWrapper() { return newWrapper(Set.of()); diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogTest.java index e94f70c636..3bea674114 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogTest.java @@ -192,6 +192,7 @@ public void before(TestInfo testInfo) { .formatted( testInfo.getTestMethod().map(Method::getName).orElse("test"), System.nanoTime()); RealmContext realmContext = () -> realmName; + QuarkusMock.installMockForType(realmContext, RealmContext.class); metaStoreManager = managerFactory.getOrCreateMetaStoreManager(realmContext); userSecretsManager = userSecretsManagerFactory.getOrCreateUserSecretsManager(realmContext); polarisContext = diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/config/DefaultConfigurationStoreTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/config/DefaultConfigurationStoreTest.java index ddd1026d97..67a8e8e6a6 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/config/DefaultConfigurationStoreTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/config/DefaultConfigurationStoreTest.java @@ -28,17 +28,14 @@ import java.time.Clock; import java.util.Map; import org.apache.polaris.core.PolarisCallContext; -import org.apache.polaris.core.PolarisDefaultDiagServiceImpl; import org.apache.polaris.core.PolarisDiagnostics; import org.apache.polaris.core.config.FeatureConfiguration; 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.entity.CatalogEntity; import org.apache.polaris.core.persistence.MetaStoreManagerFactory; import org.apache.polaris.service.config.DefaultConfigurationStore; import org.apache.polaris.service.config.FeaturesConfiguration; -import org.apache.polaris.service.persistence.InMemoryPolarisMetaStoreManagerFactory; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -47,9 +44,14 @@ @QuarkusTest @TestProfile(DefaultConfigurationStoreTest.Profile.class) public class DefaultConfigurationStoreTest { + // the key whose value is set to `false` for all realms private static final String falseByDefaultKey = "ALLOW_SPECIFYING_FILE_IO_IMPL"; + // the key whose value is set to `true` for all realms private static final String trueByDefaultKey = "ENABLE_GENERIC_TABLES"; private static final String realmOne = "realm1"; + private static final String realmTwo = "realm2"; + private static final RealmContext realmOneContext = () -> realmOne; + private static final RealmContext realmTwoContext = () -> realmTwo; public static class Profile implements QuarkusTestProfile { @@ -58,12 +60,15 @@ public Map getConfigOverrides() { return Map.of( "polaris.realm-context.realms", "realm1,realm2", - String.format("polaris.features.\"%s\"", falseByDefaultKey), - "true", String.format("polaris.features.\"%s\"", trueByDefaultKey), + "true", + String.format("polaris.features.\"%s\"", falseByDefaultKey), "false", String.format( "polaris.features.realm-overrides.\"%s\".\"%s\"", realmOne, falseByDefaultKey), + "true", + String.format( + "polaris.features.realm-overrides.\"%s\".\"%s\"", realmTwo, trueByDefaultKey), "false"); } } @@ -94,126 +99,60 @@ public void before(TestInfo testInfo) { @Test public void testGetConfiguration() { - DefaultConfigurationStore defaultConfigurationStore = - new DefaultConfigurationStore(Map.of("key1", 1, "key2", "value")); - InMemoryPolarisMetaStoreManagerFactory metastoreFactory = - new InMemoryPolarisMetaStoreManagerFactory(); - PolarisCallContext callCtx = - new PolarisCallContext( - metastoreFactory.getOrCreateSessionSupplier(() -> "realm1").get(), - new PolarisDefaultDiagServiceImpl()); - Object value = defaultConfigurationStore.getConfiguration(callCtx, "missingKeyWithoutDefault"); + Object value = configurationStore.getConfiguration(polarisContext, "missingKeyWithoutDefault"); assertThat(value).isNull(); Object defaultValue = - defaultConfigurationStore.getConfiguration( - callCtx, "missingKeyWithDefault", "defaultValue"); + configurationStore.getConfiguration( + polarisContext, "missingKeyWithDefault", "defaultValue"); assertThat(defaultValue).isEqualTo("defaultValue"); - Integer keyOne = defaultConfigurationStore.getConfiguration(callCtx, "key1"); - assertThat(keyOne).isEqualTo(1); - String keyTwo = defaultConfigurationStore.getConfiguration(callCtx, "key2"); - assertThat(keyTwo).isEqualTo("value"); + + // the falseByDefaultKey is set to false for all realms in Profile.getConfigOverrides + assertThat((Boolean) configurationStore.getConfiguration(polarisContext, falseByDefaultKey)) + .isFalse(); + // the trueByDefaultKey is set to true for all realms in Profile.getConfigOverrides + assertThat((Boolean) configurationStore.getConfiguration(polarisContext, trueByDefaultKey)) + .isTrue(); } @Test public void testGetRealmConfiguration() { - int defaultKeyOneValue = 1; - String defaultKeyTwoValue = "value"; - - int realm1KeyOneValue = 2; - int realm2KeyOneValue = 3; - String realm2KeyTwoValue = "value3"; - DefaultConfigurationStore defaultConfigurationStore = - new DefaultConfigurationStore( - Map.of("key1", defaultKeyOneValue, "key2", defaultKeyTwoValue), - Map.of( - "realm1", - Map.of("key1", realm1KeyOneValue), - "realm2", - Map.of("key1", realm2KeyOneValue, "key2", realm2KeyTwoValue))); - InMemoryPolarisMetaStoreManagerFactory metastoreFactory = - new InMemoryPolarisMetaStoreManagerFactory(); - - // check realm1 values - PolarisCallContext realm1Ctx = - new PolarisCallContext( - metastoreFactory.getOrCreateSessionSupplier(() -> "realm1").get(), - new PolarisDefaultDiagServiceImpl()); - Object value = - defaultConfigurationStore.getConfiguration(realm1Ctx, "missingKeyWithoutDefault"); - assertThat(value).isNull(); - Object defaultValue = - defaultConfigurationStore.getConfiguration( - realm1Ctx, "missingKeyWithDefault", "defaultValue"); - assertThat(defaultValue).isEqualTo("defaultValue"); - CallContext.setCurrentContext(CallContext.of(() -> "realm1", realm1Ctx)); - Integer keyOneRealm1 = defaultConfigurationStore.getConfiguration(realm1Ctx, "key1"); - assertThat(keyOneRealm1).isEqualTo(realm1KeyOneValue); - String keyTwoRealm1 = defaultConfigurationStore.getConfiguration(realm1Ctx, "key2"); - assertThat(keyTwoRealm1).isEqualTo(defaultKeyTwoValue); - - // check realm2 values - PolarisCallContext realm2Ctx = - new PolarisCallContext( - metastoreFactory.getOrCreateSessionSupplier(() -> "realm2").get(), - new PolarisDefaultDiagServiceImpl()); - CallContext.setCurrentContext(CallContext.of(() -> "realm2", realm2Ctx)); - Integer keyOneRealm2 = defaultConfigurationStore.getConfiguration(realm2Ctx, "key1"); - assertThat(keyOneRealm2).isEqualTo(realm2KeyOneValue); - String keyTwoRealm2 = defaultConfigurationStore.getConfiguration(realm2Ctx, "key2"); - assertThat(keyTwoRealm2).isEqualTo(realm2KeyTwoValue); - - // realm3 has no realm-overrides, so just returns default values - PolarisCallContext realm3Ctx = - new PolarisCallContext( - metastoreFactory.getOrCreateSessionSupplier(() -> "realm3").get(), - new PolarisDefaultDiagServiceImpl()); - CallContext.setCurrentContext(CallContext.of(() -> "realm3", realm3Ctx)); - Integer keyOneRealm3 = defaultConfigurationStore.getConfiguration(realm3Ctx, "key1"); - assertThat(keyOneRealm3).isEqualTo(defaultKeyOneValue); - String keyTwoRealm3 = defaultConfigurationStore.getConfiguration(realm3Ctx, "key2"); - assertThat(keyTwoRealm3).isEqualTo(defaultKeyTwoValue); - } - - // TODO simplify once DefaultConfigrationStore doesn't rely on CallContext.getCurrentContext - private void setCurrentRealm(String realmName) { - RealmContext realmContext = () -> realmName; - QuarkusMock.installMockForType(realmContext, RealmContext.class); - CallContext.setCurrentContext( - new CallContext() { - @Override - public RealmContext getRealmContext() { - return realmContext; - } - - @Override - public PolarisCallContext getPolarisCallContext() { - return CallContext.getCurrentContext().getPolarisCallContext(); - } + // check the realmOne configuration + QuarkusMock.installMockForType(realmOneContext, RealmContext.class); + // the falseByDefaultKey is set to `false` for all realms, but overwrite with value `true` for + // realmOne. + assertThat((Boolean) configurationStore.getConfiguration(polarisContext, falseByDefaultKey)) + .isTrue(); + // the trueByDefaultKey is set to `false` for all realms, no overwrite for realmOne + assertThat((Boolean) configurationStore.getConfiguration(polarisContext, trueByDefaultKey)) + .isTrue(); - @Override - public Map contextVariables() { - return CallContext.getCurrentContext().contextVariables(); - } - }); + // check the realmTwo configuration + QuarkusMock.installMockForType(realmTwoContext, RealmContext.class); + // the falseByDefaultKey is set to `false` for all realms, no overwrite for realmTwo + assertThat((Boolean) configurationStore.getConfiguration(polarisContext, falseByDefaultKey)) + .isFalse(); + // the trueByDefaultKey is set to `false` for all realms, and overwrite with value `false` for + // realmTwo + assertThat((Boolean) configurationStore.getConfiguration(polarisContext, trueByDefaultKey)) + .isFalse(); } @Test public void testInjectedConfigurationStore() { - // Feature override makes this `false` - boolean featureOverrideValue = + // the default value for trueByDefaultKey is `true` + boolean featureDefaultValue = configurationStore.getConfiguration(polarisContext, trueByDefaultKey); - assertThat(featureOverrideValue).isFalse(); + assertThat(featureDefaultValue).isTrue(); - // Feature override value makes this `true` - setCurrentRealm("not-" + realmOne); - boolean realmOverrideValue = - configurationStore.getConfiguration(polarisContext, falseByDefaultKey); - assertThat(realmOverrideValue).isTrue(); + QuarkusMock.installMockForType(realmTwoContext, RealmContext.class); + // the value for falseByDefaultKey is `false`, and no realm override for realmTwo + boolean realmTwoValue = configurationStore.getConfiguration(polarisContext, falseByDefaultKey); + assertThat(realmTwoValue).isFalse(); - // Now, realm override value makes this `false` - setCurrentRealm(realmOne); - realmOverrideValue = configurationStore.getConfiguration(polarisContext, falseByDefaultKey); - assertThat(realmOverrideValue).isFalse(); + // Now, realmOne override falseByDefaultKey to `True` + QuarkusMock.installMockForType(realmOneContext, RealmContext.class); + boolean realmOneValue = configurationStore.getConfiguration(polarisContext, falseByDefaultKey); + assertThat(realmOneValue).isTrue(); assertThat(configurationStore).isInstanceOf(DefaultConfigurationStore.class); } @@ -226,12 +165,16 @@ public void testInjectedFeaturesConfiguration() { .containsKeys(falseByDefaultKey, trueByDefaultKey) .allSatisfy((key, value) -> assertThat(value).doesNotContain(realmOne)); - assertThat(featuresConfiguration.realmOverrides()).hasSize(1); + assertThat(featuresConfiguration.realmOverrides()).hasSize(2); assertThat(featuresConfiguration.realmOverrides()).containsKey(realmOne); assertThat(featuresConfiguration.realmOverrides().get(realmOne).overrides()).hasSize(1); assertThat(featuresConfiguration.realmOverrides().get(realmOne).overrides()) .containsKey(falseByDefaultKey); + + assertThat(featuresConfiguration.realmOverrides().get(realmTwo).overrides()).hasSize(1); + assertThat(featuresConfiguration.realmOverrides().get(realmTwo).overrides()) + .containsKey(trueByDefaultKey); } @Test diff --git a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/task/TableCleanupTaskHandlerTest.java b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/task/TableCleanupTaskHandlerTest.java index 5e39028c92..d4147252f3 100644 --- a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/task/TableCleanupTaskHandlerTest.java +++ b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/task/TableCleanupTaskHandlerTest.java @@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import io.quarkus.test.junit.QuarkusMock; import io.quarkus.test.junit.QuarkusTest; import jakarta.annotation.Nonnull; import jakarta.inject.Inject; @@ -98,6 +99,7 @@ public FileIO loadFileIO( @BeforeEach void setup() { + QuarkusMock.installMockForType(realmContext, RealmContext.class); PolarisCallContext polarisCallContext = new PolarisCallContext( metaStoreManagerFactory.getOrCreateSessionSupplier(realmContext).get(), diff --git a/service/common/src/main/java/org/apache/polaris/service/config/DefaultConfigurationStore.java b/service/common/src/main/java/org/apache/polaris/service/config/DefaultConfigurationStore.java index 8d9fd0e430..5bc4fe51ca 100644 --- a/service/common/src/main/java/org/apache/polaris/service/config/DefaultConfigurationStore.java +++ b/service/common/src/main/java/org/apache/polaris/service/config/DefaultConfigurationStore.java @@ -22,47 +22,55 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import java.util.Map; +import java.util.Optional; import org.apache.polaris.core.PolarisCallContext; import org.apache.polaris.core.config.PolarisConfigurationStore; -import org.apache.polaris.core.context.CallContext; +import org.apache.polaris.core.context.RealmContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @ApplicationScoped public class DefaultConfigurationStore implements PolarisConfigurationStore { + Logger LOGGER = LoggerFactory.getLogger(DefaultConfigurationStore.class); private final Map defaults; private final Map> realmOverrides; + @Inject private Instance realmContextInstance; // FIXME the whole PolarisConfigurationStore + PolarisConfiguration needs to be refactored // to become a proper Quarkus configuration object @Inject public DefaultConfigurationStore( ObjectMapper objectMapper, FeaturesConfiguration configurations) { - this( - configurations.parseDefaults(objectMapper), - configurations.parseRealmOverrides(objectMapper)); - } - - public DefaultConfigurationStore(Map defaults) { - this(defaults, Map.of()); - } - - public DefaultConfigurationStore( - Map defaults, Map> realmOverrides) { - this.defaults = Map.copyOf(defaults); - this.realmOverrides = Map.copyOf(realmOverrides); + this.defaults = Map.copyOf(configurations.parseDefaults(objectMapper)); + this.realmOverrides = Map.copyOf(configurations.parseRealmOverrides(objectMapper)); } @Override public @Nullable T getConfiguration(@Nonnull PolarisCallContext ctx, String configName) { - String realm = CallContext.getCurrentContext().getRealmContext().getRealmIdentifier(); + if (!realmContextInstance.isUnsatisfied()) { + RealmContext realmContext = realmContextInstance.get(); + String realm = realmContext.getRealmIdentifier(); + LOGGER.debug("Get configuration value for {} with realm {}", configName, realm); + @SuppressWarnings("unchecked") + T confgValue = + (T) + Optional.ofNullable(realmOverrides.getOrDefault(realm, Map.of()).get(configName)) + .orElseGet(() -> getDefaultConfiguration(configName)); + return confgValue; + } else { + LOGGER.debug( + "No RealmContext is injected when lookup value for configuration {} ", configName); + return getDefaultConfiguration(configName); + } + } + + private @Nullable T getDefaultConfiguration(String configName) { @SuppressWarnings("unchecked") - T confgValue = - (T) - realmOverrides - .getOrDefault(realm, Map.of()) - .getOrDefault(configName, defaults.get(configName)); + T confgValue = (T) defaults.get(configName); return confgValue; } } diff --git a/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java b/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java index 4301fe9933..b9b72fb634 100644 --- a/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java +++ b/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java @@ -20,6 +20,8 @@ import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import jakarta.ws.rs.core.SecurityContext; import java.security.Principal; import java.time.Clock; @@ -53,7 +55,6 @@ import org.apache.polaris.service.catalog.iceberg.IcebergCatalogAdapter; import org.apache.polaris.service.catalog.io.FileIOFactory; import org.apache.polaris.service.catalog.io.MeasuredFileIOFactory; -import org.apache.polaris.service.config.DefaultConfigurationStore; import org.apache.polaris.service.config.RealmEntityManagerFactory; import org.apache.polaris.service.config.ReservedProperties; import org.apache.polaris.service.context.catalog.CallContextCatalogFactory; @@ -93,6 +94,21 @@ public interface FileIOFactorySupplier PolarisConfigurationStore, FileIOFactory> {} + private static class MockedConfigurationStore implements PolarisConfigurationStore { + private final Map defaults; + + public MockedConfigurationStore(Map defaults) { + this.defaults = Map.copyOf(defaults); + } + + @Override + public @Nullable T getConfiguration(@Nonnull PolarisCallContext ctx, String configName) { + @SuppressWarnings("unchecked") + T confgValue = (T) defaults.get(configName); + return confgValue; + } + } + public static Builder builder() { return new Builder(); } @@ -126,7 +142,7 @@ public Builder stsClient(StsClient stsClient) { } public TestServices build() { - DefaultConfigurationStore configurationStore = new DefaultConfigurationStore(config); + PolarisConfigurationStore configurationStore = new MockedConfigurationStore(config); PolarisDiagnostics polarisDiagnostics = Mockito.mock(PolarisDiagnostics.class); PolarisAuthorizer authorizer = Mockito.mock(PolarisAuthorizer.class);