This is an automated email from the ASF dual-hosted git repository.
roryqi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new b0aa708cd0 [#11836] fix(server): Return visible service admins as list
(#11843)
b0aa708cd0 is described below
commit b0aa708cd0409f0cd126d64b910e2f1d0996bc55
Author: roryqi <[email protected]>
AuthorDate: Fri Jul 3 14:17:23 2026 +0800
[#11836] fix(server): Return visible service admins as list (#11843)
### What changes were proposed in this pull request?
This PR updates the config servlet to return
`gravitino.authorization.serviceAdmins` as a list when it is exposed
through `gravitino.server.visibleConfigs`.
It also adds regression tests for:
- a single configured service admin returned as a JSON array
- `visibleConfigs` including service admins while the service admins
value is not configured
### Why are the changes needed?
When
`gravitino.server.visibleConfigs=gravitino.authorization.serviceAdmins`
is configured, `/configs` currently returns
`gravitino.authorization.serviceAdmins` as a raw string for a single
value. This is inconsistent with the typed config value and may break
clients expecting an array.
Fix: #11836
### Does this PR introduce _any_ user-facing change?
Yes. `/configs` now returns `gravitino.authorization.serviceAdmins` as a
JSON array when it is exposed by `gravitino.server.visibleConfigs`.
### How was this patch tested?
- `./gradlew :server:test --tests
org.apache.gravitino.server.web.TestConfigServlet`
- `git diff --check`
---
.../apache/gravitino/server/web/ConfigServlet.java | 38 +++++++++++++++++++--
.../gravitino/server/web/TestConfigServlet.java | 39 ++++++++++++++++++++++
2 files changed, 75 insertions(+), 2 deletions(-)
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
b/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
index b8bdbfaa1b..9ea12fa474 100644
--- a/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
+++ b/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
@@ -18,10 +18,14 @@
*/
package org.apache.gravitino.server.web;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServlet;
@@ -52,6 +56,9 @@ public class ConfigServlet extends HttpServlet {
ImmutableSet.of(
Configs.AUTHENTICATORS, Configs.ENABLE_AUTHORIZATION,
Configs.SCHEMA_SEPARATOR);
+ private static final ImmutableMap<String, ConfigEntry<?>>
visibleConfigEntries =
+ buildVisibleConfigEntries();
+
private final Map<String, Object> configs = Maps.newHashMap();
public ConfigServlet(ServerConfig serverConfig) {
@@ -80,9 +87,12 @@ public class ConfigServlet extends HttpServlet {
for (String config : visibleConfigs) {
String configValue = serverConfig.getRawString(config);
- if (configValue != null) {
- configs.put(config, configValue);
+ if (configValue == null) {
+ continue;
}
+
+ ConfigEntry<?> configEntry = visibleConfigEntries.get(config);
+ configs.put(config, configEntry == null ? configValue :
serverConfig.get(configEntry));
}
}
@@ -107,6 +117,30 @@ public class ConfigServlet extends HttpServlet {
}
}
+ private static ImmutableMap<String, ConfigEntry<?>>
buildVisibleConfigEntries() {
+ ImmutableMap.Builder<String, ConfigEntry<?>> builder =
ImmutableMap.builder();
+ for (Class<?> configClass :
+ ImmutableList.of(
+ Configs.class, ServerConfig.class, OAuthConfig.class,
JettyServerConfig.class)) {
+ for (Field field : configClass.getFields()) {
+ if (!Modifier.isStatic(field.getModifiers())
+ || !ConfigEntry.class.isAssignableFrom(field.getType())) {
+ continue;
+ }
+
+ try {
+ ConfigEntry<?> configEntry = (ConfigEntry<?>) field.get(null);
+ builder.put(configEntry.getKey(), configEntry);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(
+ "Failed to access config entry " + configClass.getName() + "." +
field.getName(), e);
+ }
+ }
+ }
+
+ return builder.build();
+ }
+
private void sendErrorResponse(HttpServletResponse res, String message) {
try (PrintWriter writer = res.getWriter()) {
res.setContentType("application/json;charset=utf-8");
diff --git
a/server/src/test/java/org/apache/gravitino/server/web/TestConfigServlet.java
b/server/src/test/java/org/apache/gravitino/server/web/TestConfigServlet.java
index a3ddee599f..10b163e706 100644
---
a/server/src/test/java/org/apache/gravitino/server/web/TestConfigServlet.java
+++
b/server/src/test/java/org/apache/gravitino/server/web/TestConfigServlet.java
@@ -30,6 +30,7 @@ import com.google.common.collect.Lists;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
+import java.util.Properties;
import javax.servlet.http.HttpServletResponse;
import org.apache.gravitino.Configs;
import org.apache.gravitino.auth.AuthenticatorType;
@@ -101,6 +102,44 @@ public class TestConfigServlet {
Assertions.assertEquals("test", configs.get(customConfig.getKey()));
}
+ @Test
+ public void testConfigServletWithVisibleServiceAdminsFromProperties() throws
Exception {
+ ServerConfig serverConfig = new ServerConfig(false);
+ Properties properties = new Properties();
+ properties.setProperty(Configs.VISIBLE_CONFIGS.getKey(),
Configs.SERVICE_ADMINS.getKey());
+ properties.setProperty(Configs.SERVICE_ADMINS.getKey(), "admin1,admin2");
+ serverConfig.loadFromProperties(properties);
+
+ Map<String, Object> configs = fetchConfigs(serverConfig);
+ Assertions.assertEquals(
+ Lists.newArrayList("admin1", "admin2"),
configs.get(Configs.SERVICE_ADMINS.getKey()));
+ }
+
+ @Test
+ public void testConfigServletWithVisibleTypedConfigFromProperties() throws
Exception {
+ ServerConfig serverConfig = new ServerConfig(false);
+ Properties properties = new Properties();
+ properties.setProperty(
+ Configs.VISIBLE_CONFIGS.getKey(),
Configs.REST_API_EXTENSION_PACKAGES.getKey());
+ properties.setProperty(Configs.REST_API_EXTENSION_PACKAGES.getKey(),
"pkg.one");
+ serverConfig.loadFromProperties(properties);
+
+ Map<String, Object> configs = fetchConfigs(serverConfig);
+ Assertions.assertEquals(
+ Lists.newArrayList("pkg.one"),
configs.get(Configs.REST_API_EXTENSION_PACKAGES.getKey()));
+ }
+
+ @Test
+ public void testConfigServletWithVisibleServiceAdminsButNoValue() throws
Exception {
+ ServerConfig serverConfig = new ServerConfig(false);
+ Properties properties = new Properties();
+ properties.setProperty(Configs.VISIBLE_CONFIGS.getKey(),
Configs.SERVICE_ADMINS.getKey());
+ serverConfig.loadFromProperties(properties);
+
+ Map<String, Object> configs = fetchConfigs(serverConfig);
+
Assertions.assertFalse(configs.containsKey(Configs.SERVICE_ADMINS.getKey()));
+ }
+
@Test
public void testConfigServletWithOAuthJwksValidator() throws Exception {
ServerConfig serverConfig = new ServerConfig();