Skip to content

Commit

Permalink
Allow Environment variables to populate property Maps in build time C…
Browse files Browse the repository at this point in the history
…onfig
  • Loading branch information
radcortez committed Jan 13, 2023
1 parent 4585831 commit b5c44bb
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -877,33 +877,34 @@ private Converter<?> getConverter(SmallRyeConfig config, Field field, ConverterT

/**
* We collect all properties from eligible ConfigSources, because Config#getPropertyNames exclude the active
* profiled properties, meaning that the property is written in the default config source without the profile
* prefix. This may cause issues if we run with a different profile and fallback to defaults.
* profiled properties (the property name omits the active profile prefix). If we record properties as is, we
* can have an issue when running in a different profile from the one recorded. This list includes all available
* properties in all profiles (active or not), so it is safe to fall back to different default on another
* profile.
* <br>
* We also filter the properties coming from the System with the registered roots, because we don't want to
* We also filter the properties coming from System or Env with the registered roots, because we don't want to
* record properties set by the compiling JVM (or other properties that are only related to the build).
* <br>
* Properties coming from the Environment are ignored.
*/
private Set<String> getAllProperties(final Set<String> registeredRoots) {
Set<String> properties = new HashSet<>();
for (String property : config.getPropertyNames()) {
properties.add(property);
}

for (ConfigSource configSource : config.getConfigSources()) {
// This is a BuildTimeSysPropConfigSource
if (configSource instanceof SysPropConfigSource) {
for (String propertyName : configSource.getProperties().keySet()) {
NameIterator ni = new NameIterator(propertyName);
if (configSource instanceof SysPropConfigSource || configSource instanceof EnvConfigSource) {
for (String property : configSource.getPropertyNames()) {
NameIterator ni = new NameIterator(property);
if (ni.hasNext() && PropertiesUtil.isPropertyInRoot(registeredRoots, ni)) {
properties.add(propertyName);
properties.add(property);
} else {
properties.remove(property);
}
}
} else {
// The BuildTimeEnvConfigSource returns an empty Set
properties.addAll(configSource.getPropertyNames());
}
}
for (String propertyName : config.getPropertyNames()) {
properties.add(propertyName);
}
return properties;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
package io.quarkus.runtime.configuration;

import static io.smallrye.config.PropertiesConfigSourceProvider.classPathSources;
import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOCATIONS;
import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE;
import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE_PARENT;
import static io.smallrye.config.SmallRyeConfigBuilder.META_INF_MICROPROFILE_CONFIG_PROPERTIES;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
Expand All @@ -36,15 +31,12 @@
import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigSourceInterceptorFactory;
import io.smallrye.config.DotEnvConfigSourceProvider;
import io.smallrye.config.EnvConfigSource;
import io.smallrye.config.FallbackConfigSourceInterceptor;
import io.smallrye.config.NameIterator;
import io.smallrye.config.Priorities;
import io.smallrye.config.RelocateConfigSourceInterceptor;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;
import io.smallrye.config.SysPropConfigSource;
import io.smallrye.config.common.utils.ConfigSourceUtil;

/**
*
Expand Down Expand Up @@ -100,24 +92,17 @@ public static SmallRyeConfigBuilder configBuilder(final boolean runTime, final b

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
builder.forClassLoader(classLoader);
builder.addDefaultSources();
builder.withSources(new ApplicationPropertiesConfigSourceLoader.InFileSystem());
builder.withSources(new ApplicationPropertiesConfigSourceLoader.InClassPath());
builder.withSources(new DotEnvConfigSourceProvider());
if (launchMode.isDevOrTest() && (runTime || bootstrap)) {
builder.withSources(new RuntimeOverrideConfigSource(classLoader));
}
if (runTime || bootstrap) {
builder.addDefaultSources();
// Validator only for runtime. We cannot use the current validator for build time (chicken / egg problem)
builder.addDiscoveredValidator();
builder.withDefaultValue(UUID_KEY, UUID.randomUUID().toString());
builder.withSources(new DotEnvConfigSourceProvider());
} else {
List<ConfigSource> sources = new ArrayList<>();
sources.addAll(classPathSources(META_INF_MICROPROFILE_CONFIG_PROPERTIES, classLoader));
sources.addAll(new BuildTimeDotEnvConfigSourceProvider().getConfigSources(classLoader));
sources.add(new BuildTimeEnvConfigSource());
sources.add(new BuildTimeSysPropConfigSource());
builder.withSources(sources);
}
if (addDiscovered) {
builder.addDiscoveredSources();
Expand Down Expand Up @@ -336,77 +321,9 @@ public static <T> Optional<T> getFirstOptionalValue(List<String> propertyNames,
return Optional.empty();
}

/**
* We override the EnvConfigSource, because we don't want the nothing back from getPropertiesNames at build time.
* The mapping is one way and there is no way to map them back.
*/
static class BuildTimeEnvConfigSource extends EnvConfigSource {
BuildTimeEnvConfigSource() {
super();
}

BuildTimeEnvConfigSource(final Map<String, String> propertyMap, final int ordinal) {
super(propertyMap, ordinal);
}

@Override
public Set<String> getPropertyNames() {
return Collections.emptySet();
}

@Override
public String getName() {
return "System environment";
}
}

/**
* Same as BuildTimeEnvConfigSource.
*/
static class BuildTimeDotEnvConfigSourceProvider extends DotEnvConfigSourceProvider {
public BuildTimeDotEnvConfigSourceProvider() {
super();
}

public BuildTimeDotEnvConfigSourceProvider(final String location) {
super(location);
}

@Override
protected ConfigSource loadConfigSource(final URL url, final int ordinal) throws IOException {
return new BuildTimeEnvConfigSource(ConfigSourceUtil.urlToMap(url), ordinal) {
@Override
public String getName() {
return super.getName() + "[source=" + url + "]";
}
};
}
}

/**
* We only want to include properties in the quarkus namespace.
*
* We removed the filter on the quarkus namespace due to the any prefix support for ConfigRoot. Filtering is now
* done in io.quarkus.deployment.configuration.BuildTimeConfigurationReader.ReadOperation#getAllProperties.
*/
static class BuildTimeSysPropConfigSource extends SysPropConfigSource {
public String getName() {
return "System properties";
}

@Override
public Set<String> getPropertyNames() {
return Collections.emptySet();
}
}

private static class ConfigBuilderComparator implements Comparator<ConfigBuilder> {

private static final ConfigBuilderComparator INSTANCE = new ConfigBuilderComparator();

private ConfigBuilderComparator() {
}

@Override
public int compare(ConfigBuilder o1, ConfigBuilder o2) {
return Integer.compare(o1.priority(), o2.priority());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import org.junit.jupiter.api.Test;

import io.smallrye.config.DotEnvConfigSourceProvider;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;

Expand All @@ -40,9 +41,7 @@ private SmallRyeConfig buildConfig(Map<String, String> configMap) throws IOExcep
}
}
}
builder.withSources(
new ConfigUtils.BuildTimeDotEnvConfigSourceProvider(dotEnv.toUri().toString())
.getConfigSources(Thread.currentThread().getContextClassLoader()));
builder.withSources(new DotEnvConfigSourceProvider(dotEnv.toUri().toString()));
final SmallRyeConfig config = builder.build();
Files.delete(dotEnv);
return config;
Expand All @@ -65,5 +64,4 @@ public void testProperties() throws IOException {
assertEquals("foo.bar", config.getValue("foo.bar", String.class));
assertTrue(config.getOptionalValue("foo.baz", String.class).isPresent());
}

}

0 comments on commit b5c44bb

Please sign in to comment.