Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit external configuration sources parsing in native-mode #42140

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
import io.quarkus.deployment.builditem.StaticInitConfigBuilderBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
import io.quarkus.deployment.util.ServiceUtil;
import io.quarkus.runtime.configuration.FileSystemOnlySourcesConfigBuilder;
import io.quarkus.runtime.configuration.SystemOnlySourcesConfigBuilder;
import io.quarkus.runtime.graal.InetRunTime;
import io.smallrye.config.ConfigSourceInterceptor;
Expand Down Expand Up @@ -55,13 +57,23 @@ RuntimeInitializedClassBuildItem runtimeInitializedClass() {
return new RuntimeInitializedClassBuildItem(InetRunTime.class.getName());
}

@BuildStep(onlyIf = SystemOnlySources.class)
@BuildStep(onlyIf = SystemOnlySources.class, onlyIfNot = NativeOrNativeSourcesBuild.class)
void systemOnlySources(BuildProducer<StaticInitConfigBuilderBuildItem> staticInitConfigBuilder,
BuildProducer<RunTimeConfigBuilderBuildItem> runTimeConfigBuilder) {
staticInitConfigBuilder.produce(new StaticInitConfigBuilderBuildItem(SystemOnlySourcesConfigBuilder.class.getName()));
runTimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(SystemOnlySourcesConfigBuilder.class.getName()));
}

/**
* Limit external configuration sources parsing for native executables since they are not supported see
* https://github.com/quarkusio/quarkus/issues/41994
*/
@BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
void nativeNoSources(BuildProducer<StaticInitConfigBuilderBuildItem> staticInitConfigBuilder,
BuildProducer<RunTimeConfigBuilderBuildItem> runTimeConfigBuilder) {
runTimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(FileSystemOnlySourcesConfigBuilder.class.getName()));
}

private static class SystemOnlySources implements BooleanSupplier {
ConfigBuildTimeConfig configBuildTimeConfig;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.builditem.StaticInitConfigBuilderBuildItem;
import io.quarkus.deployment.builditem.SuppressNonRuntimeConfigChangedWarningBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
import io.quarkus.deployment.configuration.BuildTimeConfigurationReader;
Expand Down Expand Up @@ -438,6 +439,56 @@ public void watchConfigFiles(BuildProducer<HotDeploymentWatchedFileBuildItem> wa
}
}

/**
* Registers configuration files for access at runtime in native-mode. Doesn't use absolute paths.
*/
@BuildStep
public NativeImageResourceBuildItem nativeConfigFiles() {
List<String> configFiles = new ArrayList<>();

SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);

// Main files
configFiles.add("application.properties");
configFiles.add("META-INF/microprofile-config.properties");
configFiles.add(".env");
configFiles.add(Paths.get("config", "application.properties").toString());

// Profiles
for (String profile : config.getProfiles()) {
configFiles.add(String.format("application-%s.properties", profile));
configFiles.add(String.format("META-INF/microprofile-config-%s.properties", profile));
configFiles.add(String.format(".env-%s", profile));
configFiles.add(Paths.get("config", String.format("application-%s.properties", profile))
.toString());
}

Optional<List<URI>> optionalLocations = config.getOptionalValues(SMALLRYE_CONFIG_LOCATIONS, URI.class);
optionalLocations.ifPresent(locations -> {
for (URI location : locations) {
Path path = location.getScheme() != null && location.getScheme().equals("file") ? Paths.get(location)
: Paths.get(location.getPath());
// Include missing files as smallrye will still try to access them at runtime
if (Files.isRegularFile(path) || !Files.exists(path)) {
configFiles.add(path.toString());
for (String profile : config.getProfiles()) {
configFiles.add(appendProfileToFilename(path, profile));
}
} else if (Files.isDirectory(path)) {
try (DirectoryStream<Path> files = Files.newDirectoryStream(path, Files::isRegularFile)) {
for (Path file : files) {
configFiles.add(file.toString());
}
} catch (IOException e) {
// Ignore
}
}
}
});

return new NativeImageResourceBuildItem(configFiles);
}

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
void unknownConfigFiles(
Expand Down Expand Up @@ -676,7 +727,6 @@ private static Set<String> discoverService(
// The discovery includes deployment modules, so we only include services available at runtime
if (QuarkusClassLoader.isClassPresentAtRuntime(service)) {
services.add(service);
reflectiveClass.produce(ReflectiveClassBuildItem.builder(service).build());
}
}
return services;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.quarkus.runtime.configuration;

import static io.smallrye.config.PropertiesConfigSourceLoader.inFileSystem;

import java.nio.file.Paths;

import io.smallrye.config.SmallRyeConfigBuilder;

public class FileSystemOnlySourcesConfigBuilder implements ConfigBuilder {
@Override
public SmallRyeConfigBuilder configBuilder(final SmallRyeConfigBuilder builder) {
return builder.setAddDefaultSources(false).addSystemSources().withSources(
inFileSystem(Paths.get(System.getProperty("user.dir"), "config", "application.properties").toUri().toString(),
260, builder.getClassLoader()));
}

@Override
public int priority() {
return Integer.MAX_VALUE;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import org.eclipse.microprofile.config.ConfigProvider;

import io.quarkus.config.yaml.runtime.NativeYamlConfigBuilder;
import io.quarkus.config.yaml.runtime.YamlConfigBuilder;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
Expand All @@ -14,6 +15,8 @@
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.RunTimeConfigBuilderBuildItem;
import io.quarkus.deployment.builditem.StaticInitConfigBuilderBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
import io.smallrye.config.SmallRyeConfig;

public final class ConfigYamlProcessor {
Expand All @@ -23,7 +26,7 @@ public FeatureBuildItem feature() {
return new FeatureBuildItem(Feature.CONFIG_YAML);
}

@BuildStep
@BuildStep(onlyIfNot = NativeOrNativeSourcesBuild.class)
public void yamlConfig(
BuildProducer<StaticInitConfigBuilderBuildItem> staticInitConfigBuilder,
BuildProducer<RunTimeConfigBuilderBuildItem> runTimeConfigBuilder) {
Expand All @@ -32,12 +35,23 @@ public void yamlConfig(
runTimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(YamlConfigBuilder.class));
}

/**
* Limit external configuration sources parsing for native executables since they are not supported see
* https://github.com/quarkusio/quarkus/issues/41994
*/
@BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
void nativeNoSources(BuildProducer<RunTimeConfigBuilderBuildItem> runTimeConfigBuilder) {
runTimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(NativeYamlConfigBuilder.class));
}

@BuildStep
void watchYamlConfig(BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles) {
List<String> configWatchedFiles = new ArrayList<>();
String userDir = System.getProperty("user.dir");

// Main files
configWatchedFiles.add("META-INF/microprofile-config.yaml");
configWatchedFiles.add("META-INF/microprofile-config.yml");
configWatchedFiles.add("application.yaml");
configWatchedFiles.add("application.yml");
configWatchedFiles.add(Paths.get(userDir, "config", "application.yaml").toAbsolutePath().toString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check previous comments about external files.

Expand All @@ -58,4 +72,31 @@ void watchYamlConfig(BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFil
watchedFiles.produce(new HotDeploymentWatchedFileBuildItem(configWatchedFile));
}
}

/**
* Registers configuration files for access at runtime in native-mode. Doesn't use absolute paths.
*/
@BuildStep
NativeImageResourceBuildItem nativeYamlConfig() {
List<String> configFiles = new ArrayList<>();

// Main files
configFiles.add("META-INF/microprofile-config.yaml");
configFiles.add("META-INF/microprofile-config.yml");
configFiles.add("application.yaml");
configFiles.add("application.yml");
configFiles.add(Paths.get("config", "application.yaml").toString());
configFiles.add(Paths.get("config", "application.yml").toString());

// Profiles
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
for (String profile : config.getProfiles()) {
configFiles.add(String.format("application-%s.yaml", profile));
configFiles.add(String.format("application-%s.yml", profile));
configFiles.add(Paths.get("config", String.format("application-%s.yaml", profile)).toString());
configFiles.add(Paths.get("config", String.format("application-%s.yml", profile)).toString());
}

return new NativeImageResourceBuildItem(configFiles);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.quarkus.config.yaml.runtime;

import io.quarkus.runtime.configuration.ConfigBuilder;
import io.smallrye.config.SmallRyeConfigBuilder;
import io.smallrye.config.source.yaml.YamlConfigSourceLoader;

public class NativeYamlConfigBuilder implements ConfigBuilder {
@Override
public SmallRyeConfigBuilder configBuilder(final SmallRyeConfigBuilder builder) {
return builder.withSources(new YamlConfigSourceLoader.InFileSystem());
}
}
Loading