Skip to content
Merged
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 @@ -492,13 +492,11 @@ void unknownConfigFiles(
LaunchModeBuildItem launchModeBuildItem,
ConfigRecorder configRecorder) throws Exception {

Set<Path> buildTimeFiles = new HashSet<>();
PathCollection rootDirectories = applicationArchives.getRootArchive().getRootDirectories();
if (!rootDirectories.isSinglePath()) {
return;
for (Path directory : rootDirectories) {
buildTimeFiles.addAll(ConfigDiagnostic.configFiles(directory));
}

Set<String> buildTimeFiles = new HashSet<>();
buildTimeFiles.addAll(ConfigDiagnostic.configFiles(rootDirectories.getSinglePath()));
buildTimeFiles.addAll(ConfigDiagnostic.configFilesFromLocations());

// Report always at build time since config folder and locations may differ from build to runtime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,25 +183,30 @@ public static Set<String> getErrorKeys() {
return new HashSet<>(errorKeys);
}

private static final String APPLICATION = "application";
private static final int APPLICATION_LENGTH = APPLICATION.length();

private static final DirectoryStream.Filter<Path> CONFIG_FILES_FILTER = new DirectoryStream.Filter<>() {
@Override
public boolean accept(final Path entry) {
// Ignore .properties, because we know these are have a default loader in core
// Ignore profile files. The loading rules require the main file to be present, so we only need the type
String filename = entry.getFileName().toString();
return Files.isRegularFile(entry) && filename.startsWith("application.") && !filename.endsWith(".properties");
// Include application files with any extension and profiled files
return Files.isRegularFile(entry)
&& filename.length() > APPLICATION_LENGTH
&& filename.startsWith(APPLICATION)
&& (filename.charAt(APPLICATION_LENGTH) == '.' || filename.charAt(APPLICATION_LENGTH) == '-');
}
};

public static Set<String> configFiles(Path configFilesLocation) throws IOException {
public static Set<Path> configFiles(Path configFilesLocation) throws IOException {
if (!Files.exists(configFilesLocation)) {
return Collections.emptySet();
}

Set<String> configFiles = new HashSet<>();
Set<Path> configFiles = new HashSet<>();
try (DirectoryStream<Path> candidates = Files.newDirectoryStream(configFilesLocation, CONFIG_FILES_FILTER)) {
for (Path candidate : candidates) {
configFiles.add(candidate.toUri().toURL().toString());
configFiles.add(candidate);
}
} catch (NotDirectoryException ignored) {
log.debugf("File %s is not a directory", configFilesLocation.toAbsolutePath());
Expand All @@ -210,10 +215,10 @@ public static Set<String> configFiles(Path configFilesLocation) throws IOExcepti
return configFiles;
}

public static Set<String> configFilesFromLocations() throws Exception {
public static Set<Path> configFilesFromLocations() throws Exception {
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);

Set<String> configFiles = new HashSet<>();
Set<Path> configFiles = new HashSet<>();
configFiles.addAll(configFiles(Paths.get(System.getProperty("user.dir"), "config")));
Optional<List<URI>> optionalLocations = config.getOptionalValues(SMALLRYE_CONFIG_LOCATIONS, URI.class);
optionalLocations.ifPresent(new Consumer<List<URI>>() {
Expand All @@ -236,27 +241,41 @@ public void accept(final List<URI> locations) {
return configFiles;
}

public static void unknownConfigFiles(final Set<String> configFiles) {
public static void unknownConfigFiles(final Set<Path> configFiles) throws Exception {
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
Set<String> configNames = new HashSet<>();
for (ConfigSource configSource : config.getConfigSources()) {
if (configSource.getName() != null && configSource.getName().contains("application")) {
if (configSource.getName() != null && configSource.getName().contains(APPLICATION)) {
configNames.add(configSource.getName());
}
}

for (String configFile : configFiles) {
// Config sources names include the full path of the file, so we can check for unknowns if the file was not loaded by a source
for (Path configFile : configFiles) {
boolean found = false;
for (String configName : configNames) {
if (configName.contains(configFile)) {
if (configName.contains(configFile.toUri().toURL().toString())) {
found = true;
break;
}
}
if (!found) {
log.warnf(
"Unrecognized configuration file %s found; Please, check if your are providing the proper extension to load the file",
configFile);
String filename = configFile.getFileName().toString();
// is a Profile aware file
if (filename.charAt(APPLICATION_LENGTH) == '-' && filename.lastIndexOf('.') != -1) {
String unprofiledConfigFile = APPLICATION + "." + filename.substring(filename.lastIndexOf('.') + 1);
String profile = filename.substring(APPLICATION_LENGTH + 1, filename.lastIndexOf('.'));
if (config.getProfiles().contains(profile)
&& !Files.exists(Path.of(configFile.getParent().toString(), unprofiledConfigFile))) {
log.warnf(
"Profiled configuration file %s is ignored; a main %s configuration file must exist in the same location to load %s",
configFile, unprofiledConfigFile, filename);
}
} else {
log.warnf(
"Unrecognized configuration file %s found; Please, check if your are providing the proper extension to load the file",
configFile);
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions docs/src/main/asciidoc/config-yaml.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ quarkus:
port: 8082
----

[IMPORTANT]
====
An `application.yaml` file must exist (even if empty) in the exact location of the profile-aware
(`application-{profile}.yaml`) file to be included in the configuration to ensure a consistent order when
loading the files.
====

== Expressions

The YAML format also supports xref:config-reference.adoc#property-expressions[property expressions], by using the same format as Java properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.List;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.stream.Collectors;

import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.junit.jupiter.api.Test;
Expand All @@ -20,15 +19,21 @@ class UnknownConfigFilesTest {
.withApplicationRoot((jar) -> jar
.addAsResource(EmptyAsset.INSTANCE, "application.properties")
.addAsResource(EmptyAsset.INSTANCE, "application-prod.properties")
.addAsResource(EmptyAsset.INSTANCE, "application.yaml"))
.addAsResource(EmptyAsset.INSTANCE, "application.yaml")
.addAsResource(EmptyAsset.INSTANCE, "application-test.toml"))
.setLogRecordPredicate(record -> record.getLevel().intValue() >= Level.WARNING.intValue())
.assertLogRecords(logRecords -> {
List<LogRecord> unknownConfigFiles = logRecords.stream()
.filter(l -> l.getMessage().startsWith("Unrecognized configuration file"))
.collect(Collectors.toList());

.toList();
assertEquals(1, unknownConfigFiles.size());
assertTrue(unknownConfigFiles.get(0).getParameters()[0].toString().contains("application.yaml"));

List<LogRecord> profiledConfigFiles = logRecords.stream()
.filter(l -> l.getMessage().startsWith("Profiled configuration file"))
.toList();
assertEquals(1, profiledConfigFiles.size());
assertTrue(profiledConfigFiles.get(0).getParameters()[0].toString().contains("application-test.toml"));
});

@Test
Expand Down
Loading