From d310df3747e4073c3104349d5d40c3d533f45e37 Mon Sep 17 00:00:00 2001 From: Roberto Cortez Date: Tue, 22 Sep 2020 17:25:34 +0100 Subject: [PATCH] Fix #363 - Multiple Configuration Profiles. --- .../ProfileConfigSourceInterceptor.java | 27 ++++-- .../ProfileConfigSourceInterceptorTest.java | 86 ++++++++++++++++--- 2 files changed, 93 insertions(+), 20 deletions(-) diff --git a/implementation/src/main/java/io/smallrye/config/ProfileConfigSourceInterceptor.java b/implementation/src/main/java/io/smallrye/config/ProfileConfigSourceInterceptor.java index 5494e2b53..40f150915 100644 --- a/implementation/src/main/java/io/smallrye/config/ProfileConfigSourceInterceptor.java +++ b/implementation/src/main/java/io/smallrye/config/ProfileConfigSourceInterceptor.java @@ -1,5 +1,8 @@ package io.smallrye.config; +import static io.smallrye.config.Converters.getImplicitConverter; +import static io.smallrye.config.Converters.newArrayConverter; + import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; @@ -27,10 +30,11 @@ public class ProfileConfigSourceInterceptor implements ConfigSourceInterceptor { } }; - private final String profile; + private final String[] profiles; public ProfileConfigSourceInterceptor(final String profile) { - this.profile = profile; + this.profiles = profile != null ? newArrayConverter(getImplicitConverter(String.class), String[].class).convert(profile) + : new String[0]; } public ProfileConfigSourceInterceptor(final ConfigSourceInterceptorContext context) { @@ -40,14 +44,14 @@ public ProfileConfigSourceInterceptor(final ConfigSourceInterceptorContext conte public ProfileConfigSourceInterceptor( final ConfigSourceInterceptorContext context, final String profileConfigName) { - this.profile = Optional.ofNullable(context.proceed(profileConfigName)).map(ConfigValue::getValue).orElse(null); + this(Optional.ofNullable(context.proceed(profileConfigName)).map(ConfigValue::getValue).orElse(null)); } @Override public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { - if (profile != null) { + if (profiles.length > 0) { final String normalizeName = normalizeName(name); - final ConfigValue profileValue = context.proceed("%" + profile + "." + normalizeName); + final ConfigValue profileValue = getProfileValue(context, normalizeName); if (profileValue != null) { try { final ConfigValue originalValue = context.proceed(normalizeName); @@ -64,6 +68,17 @@ public ConfigValue getValue(final ConfigSourceInterceptorContext context, final return context.proceed(name); } + public ConfigValue getProfileValue(final ConfigSourceInterceptorContext context, final String normalizeName) { + for (String profile : profiles) { + final ConfigValue profileValue = context.proceed("%" + profile + "." + normalizeName); + if (profileValue != null) { + return profileValue; + } + } + + return null; + } + @Override public Iterator iterateNames(final ConfigSourceInterceptorContext context) { final Set names = new HashSet<>(); @@ -79,6 +94,6 @@ public Iterator iterateValues(final ConfigSourceInterceptorContext } private String normalizeName(final String name) { - return name.startsWith("%" + profile + ".") ? name.substring(profile.length() + 2) : name; + return name.startsWith("%") ? name.substring(name.indexOf(".") + 1) : name; } } diff --git a/implementation/src/test/java/io/smallrye/config/ProfileConfigSourceInterceptorTest.java b/implementation/src/test/java/io/smallrye/config/ProfileConfigSourceInterceptorTest.java index efdd81862..a63ec352b 100644 --- a/implementation/src/test/java/io/smallrye/config/ProfileConfigSourceInterceptorTest.java +++ b/implementation/src/test/java/io/smallrye/config/ProfileConfigSourceInterceptorTest.java @@ -1,5 +1,6 @@ package io.smallrye.config; +import static io.smallrye.config.KeyValuesConfigSource.config; import static io.smallrye.config.ProfileConfigSourceInterceptor.SMALLRYE_PROFILE; import static java.util.stream.Collectors.toList; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -9,6 +10,7 @@ import java.util.HashMap; import java.util.List; +import java.util.NoSuchElementException; import java.util.stream.StreamSupport; import org.eclipse.microprofile.config.Config; @@ -19,18 +21,18 @@ public class ProfileConfigSourceInterceptorTest { @Test public void profile() { - final SmallRyeConfig config = (SmallRyeConfig) buildConfig("my.prop", "1", "%prof.my.prop", "2", SMALLRYE_PROFILE, - "prof"); + final SmallRyeConfig config = buildConfig("my.prop", "1", "%prof.my.prop", "2", SMALLRYE_PROFILE, "prof"); 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()); + assertEquals("2", config.getConfigValue("%prof.my.prop").getValue()); } @Test public void profileOnly() { - final Config config = buildConfig("my.prop", "1", "%prof.my.prop", "2", SMALLRYE_PROFILE, "prof"); + final Config config = buildConfig("%prof.my.prop", "2", SMALLRYE_PROFILE, "prof"); assertEquals("2", config.getValue("my.prop", String.class)); } @@ -59,13 +61,24 @@ public void profileExpressions() { assertEquals("2", config.getValue("my.prop", String.class)); } + @Test + void cannotExpand() { + final Config config = new SmallRyeConfigBuilder() + .addDefaultInterceptors() + .withSources(config("my.prop", "${another.prop}", SMALLRYE_PROFILE, "prof", "config_ordinal", "1000")) + .withSources(config("my.prop", "${another.prop}", "%prof.my.prop", "2", SMALLRYE_PROFILE, "prof")) + .build(); + + assertThrows(NoSuchElementException.class, () -> config.getValue("my.prop", String.class)); + } + @Test public void customConfigProfile() { final String[] configs = { "my.prop", "1", "%prof.my.prop", "2", "config.profile", "prof" }; final Config config = new SmallRyeConfigBuilder() .addDefaultSources() .addDiscoveredInterceptors() - .withSources(KeyValuesConfigSource.config(configs)) + .withSources(config(configs)) .build(); assertEquals("2", config.getValue("my.prop", String.class)); @@ -75,14 +88,11 @@ public void customConfigProfile() { public void noConfigProfile() { final String[] configs = { "my.prop", "1", "%prof.my.prop", "2" }; final Config config = new SmallRyeConfigBuilder() - .addDefaultSources() - .withSources(KeyValuesConfigSource.config(configs)) - .withInterceptors( - new ProfileConfigSourceInterceptor("prof"), - new ExpressionConfigSourceInterceptor()) + .addDefaultInterceptors() + .withSources(config(configs)) .build(); - assertEquals("2", config.getValue("my.prop", String.class)); + assertEquals("1", config.getValue("my.prop", String.class)); } @Test @@ -166,7 +176,7 @@ public void priorityProfileOverOriginal() { @Test public void propertyNames() { - final SmallRyeConfig config = (SmallRyeConfig) buildConfig("my.prop", "1", "%prof.my.prop", "2", "%prof.prof.only", "1", + final SmallRyeConfig config = buildConfig("my.prop", "1", "%prof.my.prop", "2", "%prof.prof.only", "1", SMALLRYE_PROFILE, "prof"); assertEquals("2", config.getConfigValue("my.prop").getValue()); @@ -181,16 +191,64 @@ public void propertyNames() { @Test public void profileName() { final SmallRyeConfig config = new SmallRyeConfigBuilder() - .withSources(KeyValuesConfigSource.config("my.prop", "1", "%prof.my.prop", "2")) + .withSources(config("my.prop", "1", "%prof.my.prop", "2")) .withProfile("prof") .build(); assertEquals("2", config.getConfigValue("my.prop").getValue()); } - private static Config buildConfig(String... keyValues) { + @Test + void multipleProfiles() { + SmallRyeConfig config = new SmallRyeConfigBuilder() + .withSources(config(SMALLRYE_PROFILE, "common,prof", "config_ordinal", "1000")) + .withSources(config("%common.common.prop", "1234", "%prof.my.prop", "5678")) + .addDefaultInterceptors() + .build(); + + assertEquals("1234", config.getRawValue("common.prop")); + assertEquals("5678", config.getRawValue("my.prop")); + } + + @Test + void multipleProfilesSamePriority() { + SmallRyeConfig config = new SmallRyeConfigBuilder() + .withSources(config(SMALLRYE_PROFILE, "common,prof", "config_ordinal", "1000")) + .withSources(config("%common.common.prop", "1234", "%prof.common.prop", "5678")) + .addDefaultInterceptors() + .build(); + + assertEquals("1234", config.getRawValue("common.prop")); + } + + @Test + void multipleProfilesDifferentPriorities() { + SmallRyeConfig config = new SmallRyeConfigBuilder() + .withSources(config(SMALLRYE_PROFILE, "common,prof", "config_ordinal", "1000")) + .withSources(config("%prof.common.prop", "5678", "config_ordinal", "500")) + .withSources(config("%common.common.prop", "1234", "config_ordinal", "300")) + .addDefaultInterceptors() + .build(); + + assertEquals("1234", config.getRawValue("common.prop")); + } + + @Test + void multipleProfilesDifferentPrioritiesMain() { + SmallRyeConfig config = new SmallRyeConfigBuilder() + .withSources(config(SMALLRYE_PROFILE, "common,prof", "config_ordinal", "1000")) + .withSources(config("common.prop", "9", "config_ordinal", "900")) + .withSources(config("%prof.common.prop", "5678", "config_ordinal", "500")) + .withSources(config("%common.common.prop", "1234", "config_ordinal", "300")) + .addDefaultInterceptors() + .build(); + + assertEquals("9", config.getRawValue("common.prop")); + } + + private static SmallRyeConfig buildConfig(String... keyValues) { return new SmallRyeConfigBuilder() - .withSources(KeyValuesConfigSource.config(keyValues)) + .withSources(config(keyValues)) .withInterceptors( new ProfileConfigSourceInterceptor("prof"), new ExpressionConfigSourceInterceptor())