diff --git a/bom/runtime/pom.xml b/bom/runtime/pom.xml index 6dd65b47f29d9..e139f56e7b8cc 100644 --- a/bom/runtime/pom.xml +++ b/bom/runtime/pom.xml @@ -32,7 +32,7 @@ 1.3.3 1.0.1 1.4.1 - 1.8.1 + 1.8.4 2.2.2 2.4.2 2.0.2 diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java index 161d2643da9dd..273525ababad2 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/ConfigUtils.java @@ -71,7 +71,7 @@ public static SmallRyeConfigBuilder configBuilder(final boolean runTime, final b final ApplicationPropertiesConfigSource.InJar inJar = new ApplicationPropertiesConfigSource.InJar(); final ApplicationPropertiesConfigSource.MpConfigInJar mpConfig = new ApplicationPropertiesConfigSource.MpConfigInJar(); builder.withSources(inFileSystem, inJar, mpConfig, new DotEnvConfigSource()); - builder.withInterceptors(new QuarkusProfileConfigSourceInterceptor(ProfileManager.getActiveProfile())); + builder.withProfile(ProfileManager.getActiveProfile()); builder.addDefaultInterceptors(); final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (runTime) { diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusProfileConfigSourceInterceptor.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusProfileConfigSourceInterceptor.java deleted file mode 100644 index fe6a819c1f789..0000000000000 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusProfileConfigSourceInterceptor.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.quarkus.runtime.configuration; - -import io.smallrye.config.ConfigSourceInterceptorContext; -import io.smallrye.config.ConfigValue; -import io.smallrye.config.ProfileConfigSourceInterceptor; - -class QuarkusProfileConfigSourceInterceptor extends ProfileConfigSourceInterceptor { - private final String profile; - - public QuarkusProfileConfigSourceInterceptor(final String profile) { - super(profile); - this.profile = profile; - } - - @Override - public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { - if (profile != null) { - final String normalizeName = normalizeName(name); - final ConfigValue profileValue = context.proceed("%" + profile + "." + normalizeName); - if (profileValue != null) { - return profileValue.withName(normalizeName); - } - } - - return context.proceed(name); - } - - private String normalizeName(final String name) { - return name.startsWith("%" + profile + ".") ? name.substring(profile.length() + 2) : name; - } -} diff --git a/core/runtime/src/test/java/io/quarkus/runtime/configuration/ConfigProfileTestCase.java b/core/runtime/src/test/java/io/quarkus/runtime/configuration/ConfigProfileTestCase.java index 89fddf0655b65..6b9be41d66154 100644 --- a/core/runtime/src/test/java/io/quarkus/runtime/configuration/ConfigProfileTestCase.java +++ b/core/runtime/src/test/java/io/quarkus/runtime/configuration/ConfigProfileTestCase.java @@ -1,18 +1,23 @@ package io.quarkus.runtime.configuration; -import static java.util.Collections.singletonMap; +import static java.util.stream.Collectors.toList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.StreamSupport; -import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.spi.ConfigProviderResolver; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import io.smallrye.config.ExpressionConfigSourceInterceptor; +import io.smallrye.config.ProfileConfigSourceInterceptor; import io.smallrye.config.PropertiesConfigSource; import io.smallrye.config.SmallRyeConfig; import io.smallrye.config.SmallRyeConfigBuilder; @@ -21,7 +26,6 @@ public class ConfigProfileTestCase { static ClassLoader classLoader; static ConfigProviderResolver cpr; - Config config; @BeforeAll public static void initConfig() { @@ -38,31 +42,39 @@ public void doAfter() { } } - private SmallRyeConfig buildConfig(Map configMap) { - final SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder(); - builder.withInterceptors(new QuarkusProfileConfigSourceInterceptor(ProfileManager.getActiveProfile())); - builder.withSources(new PropertiesConfigSource(configMap, "test input", 500)); - final SmallRyeConfig config = (SmallRyeConfig) builder.build(); + private SmallRyeConfigBuilder configBuilder(String... keyValues) { + return new SmallRyeConfigBuilder() + .addDefaultInterceptors() + .withSources(new PropertiesConfigSource(maps(keyValues), "test input", 500)) + .withProfile(ProfileManager.getActiveProfile()); + } + + private SmallRyeConfig buildConfig(String... keyValues) { + final SmallRyeConfig config = configBuilder(keyValues).build(); cpr.registerConfig(config, classLoader); - this.config = config; return config; } - private Map maps(Map... maps) { - Map out = new HashMap<>(); - for (Map map : maps) { - out.putAll(map); + private Map maps(String... keyValues) { + if (keyValues.length % 2 != 0) { + throw new IllegalArgumentException("keyValues array must be a multiple of 2"); + } + + Map props = new HashMap<>(); + for (int i = 0; i < keyValues.length; i += 2) { + props.put(keyValues[i], keyValues[i + 1]); } - return out; + + return props; } @Test - public void testDefaultProfile() { - final SmallRyeConfig config = buildConfig(maps( - singletonMap("foo.one", "v1"), - singletonMap("foo.two", "v2"), - singletonMap("%foo.foo.three", "f1"), - singletonMap("%prod.foo.four", "v4"))); + void defaultProfile() { + final SmallRyeConfig config = buildConfig( + "foo.one", "v1", + "foo.two", "v2", + "%foo.foo.three", "f1", + "%prod.foo.four", "v4"); assertEquals("v1", config.getValue("foo.one", String.class)); assertEquals("v2", config.getValue("foo.two", String.class)); assertFalse(config.getOptionalValue("foo.three", String.class).isPresent()); @@ -70,14 +82,14 @@ public void testDefaultProfile() { } @Test - public void testOverridenProfile() { + void overriddenProfile() { System.setProperty("quarkus.profile", "foo"); try { - final SmallRyeConfig config = buildConfig(maps( - singletonMap("foo.one", "v1"), - singletonMap("foo.two", "v2"), - singletonMap("%foo.foo.three", "f1"), - singletonMap("%prod.foo.four", "v4"))); + final SmallRyeConfig config = buildConfig( + "foo.one", "v1", + "foo.two", "v2", + "%foo.foo.three", "f1", + "%prod.foo.four", "v4"); assertEquals("v1", config.getValue("foo.one", String.class)); assertEquals("v2", config.getValue("foo.two", String.class)); assertEquals("f1", config.getValue("foo.three", String.class)); @@ -88,43 +100,195 @@ public void testOverridenProfile() { } @Test - public void testBackwardCompatibleOverridenProfile() { + void overriddenProfileHigherOrdinal() { System.setProperty("quarkus-profile", "foo"); try { - final SmallRyeConfig config = buildConfig(maps( - singletonMap("foo.one", "v1"), - singletonMap("foo.two", "v2"), - singletonMap("%foo.foo.three", "f1"), - singletonMap("%prod.foo.four", "v4"))); - assertEquals("v1", config.getValue("foo.one", String.class)); - assertEquals("v2", config.getValue("foo.two", String.class)); - assertEquals("f1", config.getValue("foo.three", String.class)); - assertFalse(config.getOptionalValue("foo.four", String.class).isPresent()); + final SmallRyeConfig config = configBuilder() + .withSources(new PropertiesConfigSource(maps("foo", "default"), "source", 1000)) + .withSources(new PropertiesConfigSource(maps("%foo.foo", "profile"), "source", 100)) + .build(); + + assertEquals("default", config.getRawValue("foo")); } finally { System.clearProperty("quarkus-profile"); } } @Test - public void testBackwardCompatibleOrdinalProfile() { + void profileNoErrorOnExpansion() { System.setProperty("quarkus-profile", "foo"); try { - final SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder(); - builder.withInterceptors(new QuarkusProfileConfigSourceInterceptor(ProfileManager.getActiveProfile())); - builder.withSources(new PropertiesConfigSource(new HashMap() { - { - put("foo", "default"); - } - }, "source", Integer.MAX_VALUE)); - builder.withSources(new PropertiesConfigSource(new HashMap() { - { - put("%foo.foo", "profile"); - } - }, "source", Integer.MIN_VALUE)); - final SmallRyeConfig config = builder.build(); - cpr.registerConfig(config, classLoader); - - assertEquals("profile", config.getValue("foo", String.class)); + final SmallRyeConfig config = configBuilder("foo", "${noExpansionAvailable}", "%foo.foo", "profile").build(); + + assertEquals("profile", config.getRawValue("foo")); + } finally { + System.clearProperty("quarkus-profile"); + } + } + + @Test + public void profile() { + System.setProperty("quarkus-profile", "prof"); + try { + final SmallRyeConfig config = buildConfig("my.prop", "1", "%prof.my.prop", "2"); + + assertEquals("2", config.getValue("my.prop", String.class)); + + assertEquals("my.prop", config.getConfigValue("my.prop").getName()); + assertEquals("my.prop", config.getConfigValue("%prof.my.prop").getName()); + } finally { + System.clearProperty("quarkus-profile"); + } + } + + @Test + public void profileOnly() { + System.setProperty("quarkus-profile", "prof"); + try { + final SmallRyeConfig config = buildConfig("my.prop", "1", "%prof.my.prop", "2"); + + assertEquals("2", config.getRawValue("my.prop")); + } finally { + System.clearProperty("quarkus-profile"); + } + } + + @Test + public void fallback() { + System.setProperty("quarkus-profile", "prof"); + try { + final SmallRyeConfig config = buildConfig("my.prop", "1"); + + assertEquals("1", config.getRawValue("my.prop")); + } finally { + System.clearProperty("quarkus-profile"); + } + } + + @Test + public void expressions() { + System.setProperty("quarkus-profile", "prof"); + System.setProperty("my.prop", "1"); + try { + final SmallRyeConfig config = buildConfig("my.prop", "1", "%prof.my.prop", "${my.prop}"); + + assertThrows(IllegalArgumentException.class, () -> config.getRawValue("my.prop")); + } finally { + System.clearProperty("quarkus-profile"); + System.clearProperty("my.prop"); + } + } + + @Test + public void profileExpressions() { + System.setProperty("quarkus-profile", "prof"); + System.setProperty("%prof.my.prop.profile", "2"); + try { + final SmallRyeConfig config = buildConfig("my.prop", "1", + "%prof.my.prop", "${%prof.my.prop.profile}", + "%prof.my.prop.profile", "2"); + + assertEquals("2", config.getRawValue("my.prop")); + } finally { + System.clearProperty("quarkus-profile"); + System.clearProperty("%prof.my.prop.profile"); + } + } + + @Test + public void customConfigProfile() { + System.setProperty("quarkus-profile", "prof"); + try { + final SmallRyeConfig config = configBuilder() + .addDefaultSources() + .withSources(new PropertiesConfigSource(maps("my.prop", "1", "%prof.my.prop", "2"), "test", 100)) + .build(); + + assertEquals("2", config.getValue("my.prop", String.class)); + } finally { + System.clearProperty("quarkus-profile"); + } + } + + @Test + public void noConfigProfile() { + final SmallRyeConfig config = configBuilder() + .addDefaultSources() + .withSources(new PropertiesConfigSource(maps("my.prop", "1", "%prof.my.prop", "2"), "test", 100)) + .withInterceptors( + new ProfileConfigSourceInterceptor("prof"), + new ExpressionConfigSourceInterceptor()) + .build(); + + assertEquals("2", config.getRawValue("my.prop")); + } + + @Test + public void priorityProfile() { + System.setProperty("quarkus-profile", "prof"); + try { + final SmallRyeConfig config = configBuilder() + .addDefaultSources() + .withSources(new PropertiesConfigSource(maps("%prof.my.prop", "higher-profile"), "higher", 200)) + .withSources(new PropertiesConfigSource(maps("my.prop", "lower", "%prof.my.prop", "lower-profile"), "lower", + 100)) + .build(); + + assertEquals("higher-profile", config.getRawValue("my.prop")); + } finally { + System.clearProperty("quarkus-profile"); + } + } + + @Test + public void priorityOverrideProfile() { + System.setProperty("quarkus-profile", "prof"); + try { + final SmallRyeConfig config = new SmallRyeConfigBuilder() + .addDefaultSources() + .withSources(new PropertiesConfigSource(maps("my.prop", "higher"), "higher", 200)) + .withSources(new PropertiesConfigSource(maps("my.prop", "lower", "%prof.my.prop", "lower-profile"), "lower", + 100)) + .build(); + + assertEquals("higher", config.getRawValue("my.prop")); + } finally { + System.clearProperty("quarkus-profile"); + } + } + + @Test + public void priorityProfileOverOriginal() { + System.setProperty("quarkus-profile", "prof"); + try { + final SmallRyeConfig config = configBuilder() + .addDefaultSources() + .withSources(new PropertiesConfigSource(maps("my.prop", "higher", "%prof.my.prop", "higher-profile"), + "higher", 200)) + .withSources(new PropertiesConfigSource(maps("my.prop", "lower", "%prof.my.prop", "lower-profile"), "lower", + 100)) + .build(); + + assertEquals("higher-profile", config.getRawValue("my.prop")); + } finally { + System.clearProperty("quarkus-profile"); + } + } + + @Test + public void propertyNames() { + System.setProperty("quarkus-profile", "prof"); + try { + final SmallRyeConfig config = buildConfig("my.prop", "1", "%prof.my.prop", "2", "%prof.prof.only", "1"); + + assertEquals("2", config.getRawValue("my.prop")); + assertEquals("1", config.getRawValue("prof.only")); + + final List properties = StreamSupport.stream(config.getPropertyNames().spliterator(), false) + .collect(toList()); + assertFalse(properties.contains("%prof.my.prop")); // We are removing profile properties in SmallRyeConfig and keep only the main name. + assertTrue(properties.contains("my.prop")); + assertTrue(properties.contains("prof.only")); } finally { System.clearProperty("quarkus-profile"); }