Skip to content

Commit

Permalink
Update SmallRye Config to 3.6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez committed Mar 10, 2024
1 parent fc5df7c commit f998802
Show file tree
Hide file tree
Showing 22 changed files with 182 additions and 141 deletions.
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
<microprofile-lra.version>2.0</microprofile-lra.version>
<microprofile-openapi.version>3.1.1</microprofile-openapi.version>
<smallrye-common.version>2.3.0</smallrye-common.version>
<smallrye-config.version>3.6.0</smallrye-config.version>
<smallrye-config.version>3.6.1</smallrye-config.version>
<smallrye-health.version>4.1.0</smallrye-health.version>
<smallrye-metrics.version>4.0.0</smallrye-metrics.version>
<smallrye-open-api.version>3.10.0</smallrye-open-api.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +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.quarkus.runtime.configuration.PropertiesUtil.filterPropertiesInRoots;
import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix;
import static io.smallrye.config.Expressions.withoutExpansion;
import static java.util.stream.Collectors.toSet;
Expand Down Expand Up @@ -81,7 +82,8 @@
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;
import io.smallrye.config.SysPropConfigSource;
import io.smallrye.config.common.utils.StringUtil;
import io.smallrye.config.common.AbstractConfigSource;
import io.smallrye.config.common.MapBackedConfigSource;

/**
* A configuration reader.
Expand Down Expand Up @@ -519,7 +521,6 @@ ReadResult run() {
buildTimeRunTimeValues.putAll(ConfigMappings.getDefaults(buildTimeRunTimeMapping));
}

SmallRyeConfig runtimeDefaultsConfig = getConfigForRuntimeDefaults();
Set<String> registeredRoots = allRoots.stream().map(RootDefinition::getName).collect(toSet());
registeredRoots.add("quarkus");
Set<String> allProperties = getAllProperties(registeredRoots);
Expand Down Expand Up @@ -599,7 +600,7 @@ ReadResult run() {
knownProperty = knownProperty || matched != null;
if (matched != null) {
// it's a run-time default (record for later)
ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
ConfigValue configValue = withoutExpansion(() -> config.getConfigValue(propertyName));
if (configValue.getValue() != null) {
runTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
}
Expand All @@ -610,7 +611,7 @@ ReadResult run() {
}
} else {
// it's not managed by us; record it
ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
ConfigValue configValue = withoutExpansion(() -> config.getConfigValue(propertyName));
if (configValue.getValue() != null) {
runTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
}
Expand Down Expand Up @@ -668,6 +669,15 @@ ReadResult run() {
}
}

Set<String> relocatesOrFallbacks = new HashSet<>();
for (String unknownBuildProperty : unknownBuildProperties) {
ConfigValue configValue = config.getConfigValue(unknownBuildProperty);
if (!unknownBuildProperties.contains(configValue.getName())) {
relocatesOrFallbacks.add(unknownBuildProperty);
}
}
unknownBuildProperties.removeAll(relocatesOrFallbacks);

return new ReadResult.Builder().setObjectsByClass(objectsByClass)
.setAllBuildTimeValues(allBuildTimeValues)
.setBuildTimeRunTimeValues(filterActiveProfileProperties(buildTimeRunTimeValues))
Expand Down Expand Up @@ -1026,66 +1036,66 @@ private Converter<?> getConverter(SmallRyeConfig config, Field field, ConverterT
* want to record properties set by the compiling JVM (or other properties that are only related to the build).
*/
private Set<String> getAllProperties(final Set<String> registeredRoots) {
Set<String> properties = new HashSet<>();

// Get all properties, including the ones generated by interceptors, but these do not include profiles
for (String property : config.getPropertyNames()) {
properties.add(property);
}

Set<String> propertiesToRemove = new HashSet<>();
Set<String> propertiesToAdd = new HashSet<>();

// Get properties per source to collect profiled properties and exclude properties that are build related
Set<String> sourcesProperties = new HashSet<>();
for (ConfigSource configSource : config.getConfigSources()) {
// only consider properties from Quarkus roots
if (configSource instanceof SysPropConfigSource || configSource instanceof EnvConfigSource
|| "PropertiesConfigSource[source=Build system]".equals(configSource.getName())) {
for (String property : configSource.getPropertyNames()) {
NameIterator ni = new NameIterator(property);
if (ni.hasNext() && PropertiesUtil.isPropertyInRoot(registeredRoots, ni)) {
propertiesToAdd.add(property);
} else {
propertiesToRemove.add(property);
if (configSource instanceof EnvConfigSource) {
propertiesToRemove.add(StringUtil.toLowerCaseAndDotted(property));
String unprofiledProperty = property;
if (property.startsWith("%")) {
int profileDot = property.indexOf('.');
if (profileDot != -1) {
unprofiledProperty = property.substring(profileDot + 1);
}
}
if (filterPropertiesInRoots(List.of(unprofiledProperty), registeredRoots).iterator().hasNext()) {
sourcesProperties.add(property);
}
}
} else {
propertiesToAdd.addAll(configSource.getPropertyNames());
sourcesProperties.addAll(configSource.getPropertyNames());
}
}

// A property may exist in an excluded source and an include source. We don't have a way to know, so we
// just remove the excluded ones and add the ones to be included, so the property is back there again
properties.removeAll(propertiesToRemove);
properties.addAll(propertiesToAdd);

return properties;
}
Set<String> properties = new HashSet<>();

/**
* Use this Config instance to record the runtime default values. We cannot use the main Config
* instance because it may record values coming from the EnvSource in build time. Environment variable values
* may be completely different between build and runtime, so it doesn't make sense to record these.
* <br>
* We do exclude the properties coming from the EnvSource, but a call to getValue may still provide a result
* coming from the EnvSource, so we need to exclude it from the sources when recording values for runtime.
* <br>
* We also do not want to completely exclude the EnvSource, because it may provide values for the build. This
* is only specific when recording the defaults.
*
* @return a new SmallRye instance without the EnvSources.
*/
private SmallRyeConfig getConfigForRuntimeDefaults() {
// We build a new Config to also apply the interceptor chain, this includes the active profile. A property
// may only exist in its profiled name format, but it requires recording in the unprofiled name
SmallRyeConfigBuilder builder = ConfigUtils.emptyConfigBuilder();
for (ConfigSource configSource : config.getConfigSources()) {
if (configSource instanceof EnvConfigSource) {
continue;
}
builder.withSources(configSource);
builder.getSources().clear();
builder.getSourceProviders().clear();
builder.setAddDefaultSources(false)
.addDiscoveredCustomizers()
.withSources(new AbstractConfigSource("SourceProperties", 100) {
@Override
public Set<String> getPropertyNames() {
return sourcesProperties;
}

@Override
public String getValue(final String propertyName) {
return config.getRawValue(propertyName);
}
});

// We also need an empty profile Config to record the properties that are not on the active profile
SmallRyeConfig config = builder.build();
for (String property : config.getPropertyNames()) {
properties.add(property);
}
return builder.build();

builder.withSources(new MapBackedConfigSource("Reset Profile",
Map.of("quarkus.profile", "",
"quarkus.test.profile", "")) {
});
config = builder.build();
properties = new HashSet<>();
for (String property : config.getPropertyNames()) {
properties.add(property);
}

return properties;
}

private Map<String, String> filterActiveProfileProperties(final Map<String, String> properties) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.jboss.logging.Logger;

import io.quarkus.runtime.ImageMode;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.common.utils.StringUtil;

Expand Down Expand Up @@ -90,8 +91,9 @@ public static void unknown(NameIterator name) {
* @param properties the set of possible unused properties
*/
public static void unknownProperties(Set<String> properties) {
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
Set<String> usedProperties = new HashSet<>();
for (String property : ConfigProvider.getConfig().getPropertyNames()) {
for (String property : config.getPropertyNames()) {
if (properties.contains(property)) {
continue;
}
Expand All @@ -114,7 +116,10 @@ public static void unknownProperties(Set<String> properties) {
}
}
if (!found) {
unknown(property);
ConfigValue configValue = config.getConfigValue(property);
if (property.equals(configValue.getName())) {
unknown(property);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion devtools/gradle/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugin-publish = "1.2.1"

# updating Kotlin here makes QuarkusPluginTest > shouldNotFailOnProjectDependenciesWithoutMain(Path) fail
kotlin = "1.9.22"
smallrye-config = "3.6.0"
smallrye-config = "3.6.1"

junit5 = "5.10.2"
assertj = "3.25.3"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.quarkus.opentelemetry.runtime.config.runtime.OTelRuntimeConfig;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.runtime.configuration.DurationConverter;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.SmallRyeConfig;
import io.vertx.core.Vertx;

Expand Down Expand Up @@ -85,22 +86,36 @@ private Map<String, String> getOtelConfigs() {
// instruct OTel that we are using the AutoConfiguredOpenTelemetrySdk
oTelConfigs.put("otel.java.global-autoconfigure.enabled", "true");

Map<String, String> otel = new HashMap<>();
Map<String, String> quarkus = new HashMap<>();
// load new properties
for (String propertyName : config.getPropertyNames()) {
ConfigValue configValue = config.getConfigValue(propertyName);
if (configValue.getValue() == null) {
continue;
}

String value = configValue.getValue();
if (propertyName.endsWith("timeout") || propertyName.endsWith("delay")) {
value = OTelDurationConverter.INSTANCE.convert(value);
}

if (propertyName.startsWith("quarkus.otel.")) {
String value = getValue(config, propertyName);
oTelConfigs.put(propertyName.substring(8), value);
quarkus.put(propertyName.substring(8), value);
} else if (propertyName.startsWith("otel.")) {
otel.put(propertyName, value);
}
}
return oTelConfigs;
}

private String getValue(SmallRyeConfig config, String propertyName) {
if (propertyName.endsWith("timeout") || propertyName.endsWith("delay")) {
return config.getValue(propertyName, OTelDurationConverter.INSTANCE);
if (oTelRuntimeConfig.mpCompatibility()) {
oTelConfigs.putAll(quarkus);
oTelConfigs.putAll(otel);
} else {
return config.getValue(propertyName, String.class);
oTelConfigs.putAll(otel);
oTelConfigs.putAll(quarkus);
}

return oTelConfigs;
}
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkus.opentelemetry.runtime.config;

import java.util.Map;

import io.smallrye.config.ConfigSourceInterceptor;
import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigSourceInterceptorFactory;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.Converters;
import io.smallrye.config.RelocateConfigSourceInterceptor;

public class MpTelemetryRelocateConfigSourceInterceptor implements ConfigSourceInterceptorFactory {
@Override
public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) {
ConfigValue mpCompatibility = context.proceed("quarkus.otel.mp.compatibility");
if (mpCompatibility != null && mpCompatibility.getValue() != null) {
if (Converters.getImplicitConverter(Boolean.class).convert(mpCompatibility.getValue())) {
return new RelocateConfigSourceInterceptor(Map.of(
"quarkus.otel.service.name", "otel.service.name",
"quarkus.otel.resource.attributes", "otel.resource.attributes"));
}
}
return new ConfigSourceInterceptor() {
@Override
public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) {
return context.proceed(name);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.smallrye.config.FallbackConfigSourceInterceptor;
import io.smallrye.config.Priorities;

@Deprecated(forRemoval = true, since = "3.9")
@Priority(Priorities.LIBRARY + 300 + 5)
public class OTelFallbackConfigSourceInterceptor extends FallbackConfigSourceInterceptor {
private final static Map<String, String> FALLBACKS = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,14 @@ public interface OTelRuntimeConfig {
*/
@WithName("otel.semconv-stability.opt-in")
Optional<String> otelSemconvStabilityOptIn();

/**
* Prioritize OpenTelemetry configuration <code>otel.</code> on top of Quarkus OpenTelemetry configuration
* <code>quarkus.otel</code>.
* <p>
* By default, Quarkus configuration has priority over OpenTelemetry configuration.
*/
@WithName("mp.compatibility")
@WithDefault("false")
boolean mpCompatibility();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.opentelemetry.runtime.config.MpTelemetryRelocateConfigSourceInterceptor
Original file line number Diff line number Diff line change
Expand Up @@ -86,31 +86,6 @@ public void testExtractMPClientPrefixAndProperty() {
assertThat(prefixAndProperty).isNull();
}

@Test
public void testGetValue() {
RestClientFallbackConfigSourceInterceptor interceptor = new RestClientFallbackConfigSourceInterceptor();
ConfigSourceInterceptorContext interceptorContext = new TestContext();
ConfigValue value;

// client properties
value = interceptor.getValue(interceptorContext, "quarkus.rest-client.prefix.url");
assertThat(value.getName()).isEqualTo("prefix/mp-rest/url");

value = interceptor.getValue(interceptorContext, "quarkus.rest-client.\"a.b.c\".url");
assertThat(value.getName()).isEqualTo("a.b.c/mp-rest/url");

// global properties
value = interceptor.getValue(interceptorContext, "quarkus.rest-client.multipart-post-encoder-mode");
assertThat(value.getName()).isEqualTo("quarkus.rest.client.multipart-post-encoder-mode");

value = interceptor.getValue(interceptorContext, "quarkus.rest-client.disable-smart-produces");
assertThat(value.getName()).isEqualTo("quarkus.rest-client-reactive.disable-smart-produces");

// special cases
value = interceptor.getValue(interceptorContext, "quarkus.rest-client.prefix.max-redirects");
assertThat(value.getName()).isEqualTo("quarkus.rest.client.max-redirects");
}

@Test
public void testIterateNames() {
RestClientFallbackConfigSourceInterceptor interceptor = new RestClientFallbackConfigSourceInterceptor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ quarkus.arc.unremovable-types=foo
quarkus.arc.unremovable-types[0]=foo

### Do not record env values in build time
bt.do.not.record=properties
bt.ok.to.record=properties
%test.bt.profile.record=properties

### mappings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ quarkus.arc.unremovable-types=foo
quarkus.arc.unremovable-types[0]=foo

### Do not record env values in build time
bt.do.not.record=properties
bt.ok.to.record=properties
%test.bt.profile.record=properties

### mappings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void rename() {
// 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.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"));
Expand All @@ -68,7 +68,7 @@ void rename() {
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"));
assertNull(buildTimeRunTimeDefaults.getValue("quarkus.rename-old.only-in-old"));
assertNotNull(config.getRawValue("quarkus.rename-old.only-in-old"));
}
}
Loading

0 comments on commit f998802

Please sign in to comment.