Support extensionless file imports
Update `ResourceConfigDataLocationResolver` so that it can import files that have no file extension. Closes gh-22280
This commit is contained in:
parent
081a7ee28c
commit
d0fce0553f
|
@ -698,6 +698,21 @@ If you want to support your own locations, see the `ConfigDataLocationResolver`
|
|||
|
||||
|
||||
|
||||
==== Importing Extensionless Files
|
||||
Some cloud platforms cannot add a file extension to volume mounted files.
|
||||
To import these extensionless files, you need to give Spring Boot a hint so that it knows how to load them.
|
||||
You can do this by putting an extension hint in square brackets.
|
||||
|
||||
For example, suppose you have a `/etc/config/myconfig` file that you wish to import as yaml.
|
||||
You can import it from your `application.properties` using the following:
|
||||
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
spring.config.import=file:/etc/config/myconfig[.yaml]
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[boot-features-external-config-files-configtree]]
|
||||
==== Using Configuration Trees
|
||||
When running applications on a cloud platform (such as Kubernetes) you often need to read config values that the platform supplies.
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Comparator;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -63,6 +64,8 @@ class ResourceConfigDataLocationResolver implements ConfigDataLocationResolver<R
|
|||
|
||||
private static final Pattern URL_PREFIX = Pattern.compile("^([a-zA-Z][a-zA-Z0-9*]*?:)(.*$)");
|
||||
|
||||
private static final Pattern EXTENSION_HINT_PATTERN = Pattern.compile("^(.*)\\[(\\.\\w+)\\](?!\\[)$");
|
||||
|
||||
private static final String NO_PROFILE = null;
|
||||
|
||||
private final Log logger;
|
||||
|
@ -183,11 +186,17 @@ class ResourceConfigDataLocationResolver implements ConfigDataLocationResolver<R
|
|||
}
|
||||
|
||||
private Set<Resolvable> getResolvablesForFile(String fileLocation, boolean optional, String profile) {
|
||||
Matcher extensionHintMatcher = EXTENSION_HINT_PATTERN.matcher(fileLocation);
|
||||
boolean extensionHintLocation = extensionHintMatcher.matches();
|
||||
if (extensionHintLocation) {
|
||||
fileLocation = extensionHintMatcher.group(1) + extensionHintMatcher.group(2);
|
||||
}
|
||||
for (PropertySourceLoader loader : this.propertySourceLoaders) {
|
||||
String extension = getLoadableFileExtension(loader, fileLocation);
|
||||
if (extension != null) {
|
||||
String root = fileLocation.substring(0, fileLocation.length() - extension.length() - 1);
|
||||
return Collections.singleton(new Resolvable(null, root, optional, profile, extension, loader));
|
||||
return Collections.singleton(new Resolvable(null, root, optional, profile,
|
||||
(!extensionHintLocation) ? extension : null, loader));
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("File extension is not known to any PropertySourceLoader. "
|
||||
|
@ -343,7 +352,7 @@ class ResourceConfigDataLocationResolver implements ConfigDataLocationResolver<R
|
|||
PropertySourceLoader loader) {
|
||||
String profileSuffix = (StringUtils.hasText(profile)) ? "-" + profile : "";
|
||||
this.directory = directory;
|
||||
this.resourceLocation = rootLocation + profileSuffix + "." + extension;
|
||||
this.resourceLocation = rootLocation + profileSuffix + ((extension != null) ? "." + extension : "");
|
||||
this.optional = optional;
|
||||
this.profile = profile;
|
||||
this.loader = loader;
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
|
|||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
||||
import org.springframework.boot.logging.DeferredLog;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
@ -206,6 +207,17 @@ public class ResourceConfigDataLocationResolverTests {
|
|||
.satisfies((ex) -> assertThat(ex.getCause()).hasMessageStartingWith("File extension is not known"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveWhenLocationUsesOptionalExtensionSyntaxResolves() throws Exception {
|
||||
String location = "classpath:/application-props-no-extension[.properties]";
|
||||
List<ResourceConfigDataLocation> locations = this.resolver.resolve(this.context, location, true);
|
||||
assertThat(locations.size()).isEqualTo(1);
|
||||
ResourceConfigDataLocation resolved = locations.get(0);
|
||||
assertThat(resolved.getResource().getFilename()).endsWith("application-props-no-extension");
|
||||
PropertySource<?> propertySource = resolved.load().get(0);
|
||||
assertThat(propertySource.getProperty("withnotext")).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveProfileSpecificReturnsProfileSpecificFiles() {
|
||||
String location = "classpath:/configdata/properties/";
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
withnotext=test
|
Loading…
Reference in New Issue