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

Support multiple profile names in dynamic property names #1080

Merged
merged 1 commit into from
Jan 8, 2024
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 @@ -84,9 +84,48 @@ public String[] getProfiles() {

public String normalizeName(final String name) {
if (name.length() > 0 && name.charAt(0) == '%') {
for (String profile : profiles) {
if (name.startsWith(profile + ".", 1)) {
return name.substring(profile.length() + 2);
int profilesEnd = name.indexOf('.', 1);
int multipleSplit = -1;
for (int i = 1; i < profilesEnd; i++) {
if (name.charAt(i) == ',') {
multipleSplit = i;
break;
}
}

if (multipleSplit == -1) {
// Single profile property name (%profile.foo.bar)
for (String profile : profiles) {
if (profilesEnd == profile.length() + 1 && name.regionMatches(1, profile, 0, profile.length())) {
return name.substring(profilesEnd + 1);
}
}
} else {
// Multiple profile property name (%profile,another.foo.bar)
int nextSplit = multipleSplit;
int toOffset = 1;
while (nextSplit != -1) {
for (String profile : profiles) {
char expectedEnd = name.charAt(toOffset + profile.length());
if ((expectedEnd == '.' || expectedEnd == ',') &&
name.regionMatches(toOffset, profile, 0, profile.length())) {
return name.substring(profilesEnd + 1);
}
}

toOffset = nextSplit + 1;
nextSplit = -1;

for (int i = toOffset; i < profilesEnd; i++) {
if (name.charAt(i) == ',') {
nextSplit = i;
break;
}
}

if (toOffset < profilesEnd && nextSplit == -1) {
nextSplit = profilesEnd;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,10 @@ public List<InterceptorWithPriority> getInterceptors() {
return interceptors;
}

public List<String> getProfiles() {
return profiles;
}

public ConfigValidator getValidator() {
if (isAddDiscoveredValidator()) {
this.validator = discoverValidator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.NoSuchElementException;
import java.util.OptionalInt;
import java.util.Set;
import java.util.stream.StreamSupport;

import org.eclipse.microprofile.config.Config;
import org.junit.jupiter.api.Test;
Expand All @@ -30,7 +31,7 @@
class ProfileConfigSourceInterceptorTest {
@Test
void profile() {
final Config config = buildConfig("my.prop", "1", "%prof.my.prop", "2", SMALLRYE_CONFIG_PROFILE, "prof");
SmallRyeConfig config = buildConfig("my.prop", "1", "%prof.my.prop", "2", SMALLRYE_CONFIG_PROFILE, "prof");

assertEquals("2", config.getValue("my.prop", String.class));

Expand All @@ -41,28 +42,28 @@ void profile() {

@Test
void profileOnly() {
final Config config = buildConfig("%prof.my.prop", "2", SMALLRYE_CONFIG_PROFILE, "prof");
SmallRyeConfig config = buildConfig("%prof.my.prop", "2", SMALLRYE_CONFIG_PROFILE, "prof");

assertEquals("2", config.getValue("my.prop", String.class));
}

@Test
void fallback() {
final Config config = buildConfig("my.prop", "1", SMALLRYE_CONFIG_PROFILE, "prof");
SmallRyeConfig config = buildConfig("my.prop", "1", SMALLRYE_CONFIG_PROFILE, "prof");

assertEquals("1", config.getValue("my.prop", String.class));
}

@Test
void expressions() {
final Config config = buildConfig("my.prop", "1", "%prof.my.prop", "${my.prop}", SMALLRYE_CONFIG_PROFILE, "prof");
SmallRyeConfig config = buildConfig("my.prop", "1", "%prof.my.prop", "${my.prop}", SMALLRYE_CONFIG_PROFILE, "prof");

assertThrows(IllegalArgumentException.class, () -> config.getValue("my.prop", String.class));
}

@Test
void profileExpressions() {
final Config config = buildConfig("my.prop", "1",
SmallRyeConfig config = buildConfig("my.prop", "1",
"%prof.my.prop", "${%prof.my.prop.profile}",
"%prof.my.prop.profile", "2",
SMALLRYE_CONFIG_PROFILE, "prof");
Expand All @@ -72,7 +73,7 @@ void profileExpressions() {

@Test
void cannotExpand() {
final Config config = new SmallRyeConfigBuilder()
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withSources(config("my.prop", "${another.prop}", SMALLRYE_CONFIG_PROFILE, "prof", "config_ordinal", "1000"))
.withSources(config("my.prop", "${another.prop}", "%prof.my.prop", "2", SMALLRYE_CONFIG_PROFILE, "prof"))
Expand All @@ -83,8 +84,8 @@ void cannotExpand() {

@Test
void customConfigProfile() {
final String[] configs = { "my.prop", "1", "%prof.my.prop", "2", "config.profile", "prof" };
final Config config = new SmallRyeConfigBuilder()
String[] configs = { "my.prop", "1", "%prof.my.prop", "2", "config.profile", "prof" };
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultSources()
.addDiscoveredInterceptors()
.withSources(config(configs))
Expand All @@ -95,8 +96,8 @@ void customConfigProfile() {

@Test
void noConfigProfile() {
final String[] configs = { "my.prop", "1", "%prof.my.prop", "2" };
final Config config = new SmallRyeConfigBuilder()
String[] configs = { "my.prop", "1", "%prof.my.prop", "2" };
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withSources(config(configs))
.build();
Expand All @@ -106,7 +107,7 @@ void noConfigProfile() {

@Test
void priorityProfile() {
final Config config = new SmallRyeConfigBuilder()
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withProfile("prof")
.withSources(
Expand All @@ -130,7 +131,7 @@ void priorityProfile() {

@Test
void priorityOverrideProfile() {
final Config config = new SmallRyeConfigBuilder()
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withSources(
new MapBackedConfigSource("higher", new HashMap<String, String>() {
Expand All @@ -153,7 +154,7 @@ void priorityOverrideProfile() {

@Test
void priorityProfileOverOriginal() {
final Config config = new SmallRyeConfigBuilder()
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withProfile("prof")
.withSources(
Expand All @@ -178,30 +179,36 @@ void priorityProfileOverOriginal() {

@Test
void propertyNames() {
final Config config = buildConfig("my.prop", "1", "%prof.my.prop", "2", "%prof.prof.only", "1",
SmallRyeConfig config = buildConfig(
"my.prop", "1",
"%prof.my.prop", "2",
"%prof.prof.only", "1",
"%inactive.prop", "1",
SMALLRYE_CONFIG_PROFILE, "prof");

assertEquals("2", config.getConfigValue("my.prop").getValue());
assertEquals("1", config.getConfigValue("prof.only").getValue());

final List<String> properties = stream(config.getPropertyNames().spliterator(), false).collect(toList());
List<String> properties = stream(config.getPropertyNames().spliterator(), false).collect(toList());
assertFalse(properties.contains("%prof.my.prop"));
assertTrue(properties.contains("my.prop"));
assertTrue(properties.contains("prof.only"));
// Inactive profile properties are included. We may need to revise this
assertTrue(properties.contains("%inactive.prop"));
}

@Test
void excludePropertiesFromInactiveProfiles() {
final Config config = buildConfig("%prof.my.prop", "1", "%foo.another", "2");
SmallRyeConfig config = buildConfig("%prof.my.prop", "1", "%foo.another", "2");

final List<String> properties = stream(config.getPropertyNames().spliterator(), false).collect(toList());
List<String> properties = stream(config.getPropertyNames().spliterator(), false).collect(toList());
assertTrue(properties.contains("my.prop"));
assertFalse(properties.contains("another"));
}

@Test
void profileName() {
final SmallRyeConfig config = new SmallRyeConfigBuilder()
SmallRyeConfig config = new SmallRyeConfigBuilder()
.withSources(config("my.prop", "1", "%prof.my.prop", "2"))
.withProfile("prof")
.build();
Expand Down Expand Up @@ -371,7 +378,7 @@ void parentProfileInActiveProfileWithRelocate() {
SmallRyeConfig config = new SmallRyeConfigBuilder()
.withInterceptorFactories(new ConfigSourceInterceptorFactory() {
@Override
public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) {
public ConfigSourceInterceptor getInterceptor(ConfigSourceInterceptorContext context) {
Map<String, String> relocations = new HashMap<>();
relocations.put(SMALLRYE_CONFIG_PROFILE_PARENT, "quarkus.config.profile.parent");

Expand Down Expand Up @@ -482,7 +489,8 @@ void multipleProfileProperty() {
.withSources(config("%prod,dev.my.prop", "value", "%prod,dev.my.override", "value", "config_ordinal", "100"))
.withSources(config("%dev.my.prop", "minimal", "config_ordinal", "0"))
.withSources(config("%prod,dev.another.prop", "multi", "%prod.another.prop", "single"))
.withSources(config("%common,prod,dev.triple.prop", "triple", "%common,prod.triple.prop", "double"));
.withSources(config("%common,prod,dev.triple.prop", "triple", "%common,prod.triple.prop", "double"))
.withSources(config("%commonone,prodone,devone.prop.start.with", "1"));

SmallRyeConfig prod = builder.withProfile("prod").build();
assertEquals("value", prod.getRawValue("my.prop"));
Expand All @@ -491,16 +499,35 @@ void multipleProfileProperty() {
assertEquals("override", prod.getRawValue("%prod.my.override"));
assertEquals("single", prod.getRawValue("another.prop"));
assertEquals("double", prod.getRawValue("triple.prop"));
Set<String> prodNames = StreamSupport.stream(prod.getPropertyNames().spliterator(), false).collect(toSet());
assertTrue(prodNames.contains("my.prop"));
assertTrue(prodNames.contains("my.override"));
assertTrue(prodNames.contains("another.prop"));
assertTrue(prodNames.contains("triple.prop"));
assertFalse(prodNames.contains("prop.start.with"));
builder.getProfiles().clear();

SmallRyeConfig dev = builder.withProfile("dev").build();
assertEquals("value", dev.getRawValue("my.prop"));
assertEquals("value", dev.getRawValue("%dev.my.prop"));
assertEquals("value", dev.getRawValue("my.override"));
assertEquals("value", dev.getRawValue("%dev.my.override"));
assertEquals("triple", dev.getRawValue("triple.prop"));
Set<String> devNames = StreamSupport.stream(dev.getPropertyNames().spliterator(), false).collect(toSet());
assertTrue(devNames.contains("my.prop"));
assertTrue(devNames.contains("my.override"));
assertTrue(devNames.contains("another.prop"));
assertTrue(devNames.contains("triple.prop"));
assertFalse(devNames.contains("prop.start.with"));
builder.getProfiles().clear();

SmallRyeConfig common = builder.withProfile("common").build();
assertEquals("double", common.getRawValue("triple.prop"));
Set<String> commonNames = StreamSupport.stream(common.getPropertyNames().spliterator(), false).collect(toSet());
assertTrue(commonNames.contains("triple.prop"));
assertFalse(commonNames.contains("my.prop"));
assertFalse(commonNames.contains("prop.start.with"));
builder.getProfiles().clear();
}

@Test
Expand Down
Loading