Skip to content

Commit

Permalink
Update SmallRye Config to 2.8.1
Browse files Browse the repository at this point in the history
Record config properties with ConfigValue
This will improve the support of the fallback and relocation mechanisms
  • Loading branch information
radcortez committed Dec 22, 2021
1 parent 3cc2737 commit fe6d9d0
Show file tree
Hide file tree
Showing 14 changed files with 297 additions and 72 deletions.
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<microprofile-jwt.version>1.2</microprofile-jwt.version>
<microprofile-lra.version>1.0</microprofile-lra.version>
<smallrye-common.version>1.8.0</smallrye-common.version>
<smallrye-config.version>2.7.0</smallrye-config.version>
<smallrye-config.version>2.8.1</smallrye-config.version>
<smallrye-health.version>3.1.2</smallrye-health.version>
<smallrye-metrics.version>3.0.4</smallrye-metrics.version>
<smallrye-open-api.version>2.1.16</smallrye-open-api.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import static io.quarkus.deployment.util.ReflectUtil.toError;
import static io.quarkus.deployment.util.ReflectUtil.typeOfParameter;
import static io.quarkus.deployment.util.ReflectUtil.unwrapInvocationTargetException;
import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE;
import static io.smallrye.config.Expressions.withoutExpansion;
import static java.util.stream.Collectors.toSet;

import java.lang.reflect.Constructor;
Expand Down Expand Up @@ -59,9 +59,9 @@
import io.quarkus.runtime.configuration.NameIterator;
import io.quarkus.runtime.configuration.ProfileManager;
import io.quarkus.runtime.configuration.PropertiesUtil;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.Converters;
import io.smallrye.config.EnvConfigSource;
import io.smallrye.config.Expressions;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;
import io.smallrye.config.SysPropConfigSource;
Expand Down Expand Up @@ -316,15 +316,22 @@ ReadResult run() {
// build time patterns
Container matched = buildTimePatternMap.match(ni);
if (matched instanceof FieldContainer) {
allBuildTimeValues.put(propertyName,
config.getOptionalValue(propertyName, String.class).orElse(""));
ConfigValue configValue = config.getConfigValue(propertyName);
if (configValue.getValue() == null) {
continue;
}
allBuildTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
ni.goToEnd();
// cursor is located after group property key (if any)
getGroup((FieldContainer) matched, ni);
// we don't have to set the field because the group object init does it for us
continue;
} else if (matched != null) {
assert matched instanceof MapContainer;
ConfigValue configValue = config.getConfigValue(propertyName);
if (configValue.getValue() == null) {
continue;
}
// it's a leaf value within a map
// these must always be explicitly set
ni.goToEnd();
Expand All @@ -334,25 +341,30 @@ ReadResult run() {
// we always have to set the map entry ourselves
Field field = matched.findField();
Converter<?> converter = getConverter(config, field, ConverterType.of(field));
map.put(key, config.getValue(propertyName, converter));
allBuildTimeValues.put(propertyName,
config.getOptionalValue(propertyName, String.class).orElse(""));
map.put(key, config.convertValue(configValue.getNameProfiled(), configValue.getValue(), converter));
allBuildTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
continue;
}
// build time (run time visible) patterns
ni.goToStart();
matched = buildTimeRunTimePatternMap.match(ni);
if (matched instanceof FieldContainer) {
ConfigValue configValue = config.getConfigValue(propertyName);
if (configValue.getValue() == null) {
continue;
}
ni.goToEnd();
// cursor is located after group property key (if any)
getGroup((FieldContainer) matched, ni);
allBuildTimeValues.put(propertyName,
config.getOptionalValue(propertyName, String.class).orElse(""));
buildTimeRunTimeVisibleValues.put(propertyName,
config.getOptionalValue(propertyName, String.class).orElse(""));
allBuildTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
buildTimeRunTimeVisibleValues.put(configValue.getNameProfiled(), configValue.getValue());
continue;
} else if (matched != null) {
assert matched instanceof MapContainer;
ConfigValue configValue = config.getConfigValue(propertyName);
if (configValue.getValue() == null) {
continue;
}
// it's a leaf value within a map
// these must always be explicitly set
ni.goToEnd();
Expand All @@ -362,36 +374,25 @@ ReadResult run() {
// we always have to set the map entry ourselves
Field field = matched.findField();
Converter<?> converter = getConverter(config, field, ConverterType.of(field));
map.put(key, config.getValue(propertyName, converter));
map.put(key, config.convertValue(configValue.getNameProfiled(), configValue.getValue(), converter));
// cache the resolved value
buildTimeRunTimeVisibleValues.put(propertyName,
config.getOptionalValue(propertyName, String.class).orElse(""));
allBuildTimeValues.put(propertyName,
config.getOptionalValue(propertyName, String.class).orElse(""));
buildTimeRunTimeVisibleValues.put(configValue.getNameProfiled(), configValue.getValue());
allBuildTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
continue;
}
// run time patterns
ni.goToStart();
matched = runTimePatternMap.match(ni);
if (matched != null) {
// it's a specified run-time default (record for later)
specifiedRunTimeDefaultValues.put(propertyName, Expressions.withoutExpansion(
() -> runtimeDefaultsConfig.getOptionalValue(propertyName, String.class).orElse("")));

continue;
}
// also check for the bootstrap properties since those need to be added to specifiedRunTimeDefaultValues as well
ni.goToStart();
matched = bootstrapPatternMap.match(ni);
if (matched != null) {
// it's a specified run-time default (record for later)
specifiedRunTimeDefaultValues.put(propertyName, Expressions.withoutExpansion(
() -> runtimeDefaultsConfig.getOptionalValue(propertyName, String.class).orElse("")));
// Record everything else as runtime default values
ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
if (configValue.getValue() != null) {
specifiedRunTimeDefaultValues.put(configValue.getNameProfiled(), configValue.getValue());
}

} else {
// it's not managed by us; record it
specifiedRunTimeDefaultValues.put(propertyName, Expressions.withoutExpansion(
() -> runtimeDefaultsConfig.getOptionalValue(propertyName, String.class).orElse("")));
ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
if (configValue.getValue() != null) {
specifiedRunTimeDefaultValues.put(configValue.getNameProfiled(), configValue.getValue());
}
}
}

Expand Down Expand Up @@ -775,9 +776,7 @@ private Set<String> getAllProperties(final Set<String> registeredRoots) {
* @return a new SmallRye instance without the EnvSources.
*/
private SmallRyeConfig getConfigForRuntimeDefaults() {
SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder();
builder.withDefaultValue(SMALLRYE_CONFIG_PROFILE, ProfileManager.getActiveProfile());
builder.addDefaultInterceptors();
SmallRyeConfigBuilder builder = ConfigUtils.emptyConfigBuilder();
for (ConfigSource configSource : config.getConfigSources()) {
if (configSource instanceof EnvConfigSource) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorConte

@Override
public OptionalInt getPriority() {
return OptionalInt.of(Priorities.LIBRARY + 600 - 5);
return OptionalInt.of(Priorities.LIBRARY + 200 - 5);
}
});

Expand All @@ -157,7 +157,7 @@ public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorConte

@Override
public OptionalInt getPriority() {
return OptionalInt.of(Priorities.LIBRARY + 400 - 5);
return OptionalInt.of(Priorities.LIBRARY + 600 - 5);
}
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.quarkus.config;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Optional;

import javax.inject.Inject;

import org.eclipse.microprofile.config.spi.ConfigSource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.extest.runtime.config.rename.RenameConfig;
import io.quarkus.test.QuarkusUnitTest;
import io.smallrye.config.SmallRyeConfig;

public class RenameConfigTest {
@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));

@Inject
RenameConfig renameConfig;
@Inject
SmallRyeConfig config;

@Test
void rename() {
assertEquals("1234", renameConfig.prop);
assertEquals("1234", config.getRawValue("quarkus.rename.prop"));

assertEquals("only-in-new", renameConfig.onlyInNew);
assertEquals("only-in-old", renameConfig.onlyInOld);
assertEquals("new", renameConfig.inBoth);

// This will always return values. It lookups on "rename" first and "rename-old" next
assertEquals("only-in-new", config.getRawValue("quarkus.rename.only-in-new"));
assertEquals("only-in-old", config.getRawValue("quarkus.rename.only-in-old"));
assertEquals("new", config.getRawValue("quarkus.rename.in-both"));

assertEquals("only-in-new", config.getRawValue("quarkus.rename-old.only-in-new"));
assertEquals("only-in-old", config.getRawValue("quarkus.rename-old.only-in-old"));
assertEquals("new", config.getRawValue("quarkus.rename-old.in-both"));

assertEquals("old-default", config.getRawValue("quarkus.rename.with-default"));
assertEquals("old-default", config.getRawValue("quarkus.rename-old.with-default"));
assertEquals("old-default", renameConfig.withDefault);

// Make sure we only record the actual properties in the sources (and not renamed properties)
Optional<ConfigSource> configSource = config.getConfigSource("PropertiesConfigSource[source=Build time config]");
assertTrue(configSource.isPresent());
ConfigSource buildTimeRunTimeDefaults = configSource.get();

// In Build time source
assertNotNull(buildTimeRunTimeDefaults.getValue("quarkus.rename.prop"));
assertNotNull(buildTimeRunTimeDefaults.getValue("quarkus.rename.only-in-new"));
assertNotNull(buildTimeRunTimeDefaults.getValue("quarkus.rename-old.only-in-old"));
assertNotNull(buildTimeRunTimeDefaults.getValue("quarkus.rename.in-both"));
// When in both only the one that has priority (remamed) is recorded
assertNull(buildTimeRunTimeDefaults.getValue("quarkus.rename-old.in-both"));
// Relocate / Fallback properties, not in the source but values are not null when Config is queried
assertNull(buildTimeRunTimeDefaults.getValue("quarkus.rename-old.prop"));
assertNotNull(config.getRawValue("quarkus.rename-old.prop"));
assertNull(buildTimeRunTimeDefaults.getValue("quarkus.rename-old.only-in-new"));
assertNotNull(config.getRawValue("quarkus.rename-old.only-in-new"));
assertNull(buildTimeRunTimeDefaults.getValue("quarkus.rename.only-in-old"));
assertNotNull(config.getRawValue("quarkus.rename.only-in-old"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ public class UnknownConfigTest {
.assertLogRecords(logRecords -> {
Set<String> properties = logRecords.stream().flatMap(
logRecord -> Stream.of(logRecord.getParameters())).map(Object::toString).collect(Collectors.toSet());
assertEquals(1, properties.size());
assertTrue(properties.contains("quarkus.unknown.prop"));
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.extest.runtime.config.rename;

import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;

@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
public class RenameConfig {
/**
*
*/
@ConfigItem
public String prop;
/**
*
*/
@ConfigItem
public String onlyInNew;
/**
*
*/
@ConfigItem
public String onlyInOld;
/**
*
*/
@ConfigItem
public String inBoth;
/**
*
*/
@ConfigItem(defaultValue = "default")
public String withDefault;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.quarkus.extest.runtime.config.rename;

import java.util.function.Function;

import io.smallrye.config.FallbackConfigSourceInterceptor;

public class RenameConfigFallbackInterceptor extends FallbackConfigSourceInterceptor {
private static final Function<String, String> FALLBACK = name -> {
if (name.startsWith("quarkus.rename.")) {
return name.replaceFirst("quarkus\\.rename\\.", "quarkus.rename-old.");
}
return name;
};

public RenameConfigFallbackInterceptor() {
super(FALLBACK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.quarkus.extest.runtime.config.rename;

import java.util.function.Function;

import io.smallrye.config.RelocateConfigSourceInterceptor;

public class RenameConfigRelocateInterceptor extends RelocateConfigSourceInterceptor {
private static final Function<String, String> RELOCATE = name -> {
if (name.startsWith("quarkus.rename-old.")) {
return name.replaceFirst("quarkus\\.rename-old\\.", "quarkus.rename.");
}
return name;
};

public RenameConfigRelocateInterceptor() {
super(RELOCATE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package io.quarkus.extest.runtime.config.rename;

import static java.util.Collections.emptySet;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.spi.ConfigSource;

import io.quarkus.runtime.annotations.StaticInitSafe;
import io.smallrye.config.common.MapBackedConfigSource;

/**
* This simulates a build time only source to test the recording of configuration values. It is still discovered at
* runtime, but it doesn't return any configuration.
*/
@StaticInitSafe
public class RenameConfigSource extends MapBackedConfigSource {
// Because getPropertyNames() is called during SmallRyeConfig init
private int propertyNamesCallCount = 0;

private static final Map<String, String> FALLBACK_PROPERTIES = Map.of(
"quarkus.rename.prop", "1234",
"quarkus.rename.only-in-new", "only-in-new",
"quarkus.rename-old.only-in-old", "only-in-old",
"quarkus.rename.in-both", "new",
"quarkus.rename-old.in-both", "old",
"quarkus.rename-old.with-default", "old-default");

public RenameConfigSource() {
super(RenameConfigSource.class.getName(), new HashMap<>());
}

@Override
public String getValue(final String propertyName) {
if (propertyName.startsWith("quarkus.rename") && isBuildTime()) {
return FALLBACK_PROPERTIES.get(propertyName);
}
return null;
}

@Override
public Set<String> getPropertyNames() {
if (propertyNamesCallCount > 0) {
return isBuildTime() ? FALLBACK_PROPERTIES.keySet() : emptySet();
} else {
propertyNamesCallCount++;
return emptySet();
}
}

private static boolean isBuildTime() {
// We can only call this when the SmallRyeConfig is already initialized, or else we may get into a loop
Config config = ConfigProvider.getConfig();
for (ConfigSource configSource : config.getConfigSources()) {
if (configSource.getClass().getSimpleName().equals("BuildTimeEnvConfigSource")) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
io.quarkus.extest.runtime.config.rename.RenameConfigRelocateInterceptor
io.quarkus.extest.runtime.config.rename.RenameConfigFallbackInterceptor
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.extest.runtime.config.rename.RenameConfigSource
Loading

0 comments on commit fe6d9d0

Please sign in to comment.