diff --git a/changelog/unreleased/SOLR-16396-config-get-components.yml b/changelog/unreleased/SOLR-16396-config-get-components.yml new file mode 100644 index 000000000000..99a86733e031 --- /dev/null +++ b/changelog/unreleased/SOLR-16396-config-get-components.yml @@ -0,0 +1,9 @@ +title: + Migrate GET config sections updateHandler, directoryFactory, indexConfig, and codecFactory to JAX-RS. +type: changed +authors: + - name: Jalaz Kumar + nick: jaykay12 +links: + - name: SOLR-16396 + url: https://issues.apache.org/jira/browse/SOLR-16396 diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java index cc9cecc1bb56..baaf4a9f785f 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java @@ -23,6 +23,7 @@ import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; import jakarta.ws.rs.QueryParam; import org.apache.solr.client.api.model.ConfigInfoResponse; import org.apache.solr.client.api.model.ConfigOverlayResponse; @@ -68,5 +69,16 @@ ConfigZnodeVersionResponse getZnodeVersion( @DefaultValue("-1") @Parameter(description = "Expected request-params znode version") int expectedParamsVersion); + + // TODO: Keep this regex in sync with GetConfig.MIGRATED_CONFIG_COMPONENTS + @GET + @Path("/{component:updateHandler|directoryFactory|indexConfig|codecFactory}") + @StoreApiParameters + @Operation( + summary = "Fetch a config section", + tags = {"config"}) + ConfigInfoResponse getConfigComponent( + @PathParam("component") @Parameter(description = "Name of the config component") + String component); } } diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java index d61b7d2bacbc..8ea4dd3ca404 100644 --- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java @@ -225,6 +225,9 @@ private void handleGET() { .getZnodeVersion( req.getParams().getInt(ConfigOverlay.NAME, -1), req.getParams().getInt(RequestParams.NAME, -1))); + } else if (GetConfig.MIGRATED_CONFIG_COMPONENTS.contains(parts.get(1))) { + V2ApiUtils.squashIntoSolrResponseWithoutHeader( + resp, new GetConfig(req).getConfigComponent(parts.get(1))); } else { Map m = getConfigDetails(parts.get(1), req); Map val = new LinkedHashMap<>(); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java index 80d46e7bac65..806cd1b39718 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java @@ -27,6 +27,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.endpoint.ConfigApi; import org.apache.solr.client.api.model.ConfigInfoResponse; @@ -48,6 +49,11 @@ public class GetConfig extends JerseyResource implements ConfigApi.Get { + // TODO: Keep this in sync with @Path regex on ConfigApi.Get#getConfigComponent. + // TODO: Remove this set when remaining GET /config/{component} sections also migrate. + public static final Set MIGRATED_CONFIG_COMPONENTS = + Set.of("updateHandler", "directoryFactory", "indexConfig", "codecFactory"); + private final SolrQueryRequest solrQueryRequest; @Inject @@ -89,15 +95,36 @@ public ConfigZnodeVersionResponse getZnodeVersion( return response; } + @Override + @PermissionName(CONFIG_READ_PERM) + public ConfigInfoResponse getConfigComponent(String componentName) { + final var response = instantiateJerseyResponse(ConfigInfoResponse.class); + Map section = new LinkedHashMap<>(); + section.put(componentName, solrConfigAsMap().get(componentName)); + response.config = jsonSafeCopy(section); + return response; + } + + private Map solrConfigAsMap() { + return Utils.convertToMap(solrQueryRequest.getCore().getSolrConfig(), new LinkedHashMap<>()); + } + + @SuppressWarnings("unchecked") + private NullKeyTolerantMap jsonSafeCopy(Map map) { + final var jsonSafeCopy = new NullKeyTolerantMap("children"); + jsonSafeCopy.putAll((Map) Utils.getDeepCopy(map, 20, true)); + return jsonSafeCopy; + } + @SuppressWarnings({"unchecked"}) private Map buildConfigMap( SolrQueryRequest solrQueryRequest, boolean expandParams) { - Map map = - Utils.convertToMap(solrQueryRequest.getCore().getSolrConfig(), new LinkedHashMap<>()); + + Map configMap = solrConfigAsMap(); Map reqHandlers = (Map) - map.computeIfAbsent(SolrRequestHandler.TYPE, k -> new LinkedHashMap<>()); + configMap.computeIfAbsent(SolrRequestHandler.TYPE, k -> new LinkedHashMap<>()); List plugins = solrQueryRequest.getCore().getImplicitHandlers(); for (PluginInfo plugin : plugins) { if (SolrRequestHandler.TYPE.equals(plugin.type) && !reqHandlers.containsKey(plugin.name)) { @@ -111,9 +138,7 @@ private Map buildConfigMap( } } - final var jsonSafeCopy = new NullKeyTolerantMap("children"); - jsonSafeCopy.putAll((Map) Utils.getDeepCopy(map, 20, true)); - return jsonSafeCopy; + return jsonSafeCopy(configMap); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java index 6a0567c987ce..1e67cb09c503 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java @@ -28,8 +28,9 @@ /** * V2 APIs for retrieving some or all configuration relevant to a particular collection (or core). * - *

This class covers legacy AnnotatedApi paths under GET /config: /params, /params{paramset}, - * /overlay, /znodeVersion, etc. + *

This class covers legacy AnnotatedApi paths under GET /config: /params, /params{paramset}, and + * remaining {@code /config/{component}} sections not yet migrated to {@link + * org.apache.solr.client.api.endpoint.ConfigApi.Get} */ public class GetConfigAPI { private final SolrConfigHandler configHandler; @@ -63,13 +64,9 @@ public void getSingleParamSet(SolrQueryRequest req, SolrQueryResponse rsp) { "/config/query", "/config/requestHandler", "/config/searchComponent", - "/config/updateHandler", "/config/queryResponseWriter", "/config/initParams", "/config/listener", - "/config/directoryFactory", - "/config/indexConfig", - "/config/codecFactory", "/config/requestDispatcher", "/config/jmx", "/config/queryParser", diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java index 7ce43a5ff3d7..7b34a37bbb12 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java @@ -76,4 +76,19 @@ public void testGetZnodeVersionFromCollection() throws Exception { assertTrue(response.znodeVersion.overlay >= -1); assertTrue(response.znodeVersion.params >= -1); } + + @Test + public void testGetConfigComponentFromCollection() throws Exception { + for (String component : GetConfig.MIGRATED_CONFIG_COMPONENTS) { + var request = + new ConfigApi.GetConfigComponent(IndexType.COLLECTION, COLLECTION_NAME, component); + var response = request.process(cluster.getSolrClient()); + + assertNotNull(component, response); + assertNull(component, response.error); + assertNotNull(component, response.config); + assertTrue(component, response.config.containsKey(component)); + assertEquals(component, 1, response.config.size()); + } + } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java index a17d9258a180..b0fbbfa80351 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java @@ -80,4 +80,18 @@ public void testGetZnodeVersionFromCore() throws Exception { assertTrue(response.znodeVersion.overlay >= -1); assertTrue(response.znodeVersion.params >= -1); } + + @Test + public void testGetConfigComponentFromCore() throws Exception { + for (String component : GetConfig.MIGRATED_CONFIG_COMPONENTS) { + var request = new ConfigApi.GetConfigComponent(IndexType.CORE, CORE_NAME, component); + var response = request.process(solrTestRule.getSolrClient(CORE_NAME)); + + assertNotNull(component, response); + assertNull(component, response.error); + assertNotNull(component, response.config); + assertTrue(component, response.config.containsKey(component)); + assertEquals(component, 1, response.config.size()); + } + } }