This is an automated email from the ASF dual-hosted git repository.
gerlowskija pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new f6f58c0 SOLR-15490: /cluster v2 API parameter mapping tests (#204)
f6f58c0 is described below
commit f6f58c08cb2c52e30c06b916b8d984ff2ec92173
Author: Jason Gerlowski <[email protected]>
AuthorDate: Fri Jul 9 11:09:57 2021 +0000
SOLR-15490: /cluster v2 API parameter mapping tests (#204)
This commit adds unit tests that validate the parameter mapping for a
number of v2 APIs under the /cluster path.
---
.../java/org/apache/solr/handler/ClusterAPI.java | 33 +--
.../org/apache/solr/handler/CollectionsAPI.java | 5 +-
.../solr/handler/V2ClusterAPIMappingTest.java | 241 +++++++++++++++++++++
.../handler/admin/V2CollectionsAPIMappingTest.java | 7 +
4 files changed, 272 insertions(+), 14 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
index 334dbde..3f64032 100644
--- a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
@@ -20,6 +20,7 @@ package org.apache.solr.handler;
import java.util.HashMap;
import java.util.Map;
+import com.google.common.collect.Maps;
import org.apache.solr.api.Command;
import org.apache.solr.api.EndPoint;
import org.apache.solr.api.PayloadObj;
@@ -30,6 +31,7 @@ import org.apache.solr.cloud.ConfigSetCmds;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.annotation.JsonProperty;
import org.apache.solr.common.cloud.ClusterProperties;
+import org.apache.solr.common.params.CollectionParams;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.ConfigSetParams;
import org.apache.solr.common.params.DefaultSolrParams;
@@ -47,10 +49,8 @@ import static
org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
import static org.apache.solr.client.solrj.SolrRequest.METHOD.PUT;
import static
org.apache.solr.cloud.api.collections.CollectionHandlingUtils.REQUESTID;
-import static
org.apache.solr.common.params.CollectionParams.CollectionAction.ADDROLE;
-import static
org.apache.solr.common.params.CollectionParams.CollectionAction.CLUSTERPROP;
-import static
org.apache.solr.common.params.CollectionParams.CollectionAction.OVERSEERSTATUS;
-import static
org.apache.solr.common.params.CollectionParams.CollectionAction.REMOVEROLE;
+import static org.apache.solr.common.params.CollectionParams.ACTION;
+import static
org.apache.solr.common.params.CollectionParams.CollectionAction.*;
import static org.apache.solr.core.RateLimiterConfig.RL_CONFIG_KEY;
import static
org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
import static
org.apache.solr.security.PermissionNameProvider.Name.COLL_READ_PERM;
@@ -76,29 +76,33 @@ public class ClusterAPI {
path = "/cluster/aliases",
permission = COLL_READ_PERM)
public void aliases(SolrQueryRequest req, SolrQueryResponse rsp) throws
Exception {
- CollectionsHandler.CollectionOperation.LISTALIASES_OP.execute(req, rsp,
getCoreContainer().getCollectionsHandler());
+ final Map<String, Object> v1Params = Maps.newHashMap();
+ v1Params.put(ACTION,
CollectionParams.CollectionAction.LISTALIASES.lowerName);
+ collectionsHandler.handleRequestBody(wrapParams(req, v1Params), rsp);
}
@EndPoint(method = GET,
path = "/cluster/overseer",
permission = COLL_READ_PERM)
public void getOverseerStatus(SolrQueryRequest req, SolrQueryResponse rsp)
throws Exception {
-
getCoreContainer().getCollectionsHandler().handleRequestBody(wrapParams(req,
"action", OVERSEERSTATUS.toString()), rsp);
+ collectionsHandler.handleRequestBody(wrapParams(req, "action",
OVERSEERSTATUS.lowerName), rsp);
}
@EndPoint(method = GET,
path = "/cluster",
permission = COLL_READ_PERM)
public void getCluster(SolrQueryRequest req, SolrQueryResponse rsp) throws
Exception {
- CollectionsHandler.CollectionOperation.LIST_OP.execute(req, rsp,
getCoreContainer().getCollectionsHandler());
+ collectionsHandler.handleRequestBody(wrapParams(req, "action",
LIST.lowerName), rsp);
}
@EndPoint(method = DELETE,
path = "/cluster/command-status/{id}",
permission = COLL_EDIT_PERM)
public void deleteCommandStatus(SolrQueryRequest req, SolrQueryResponse rsp)
throws Exception {
- wrapParams(req, REQUESTID, req.getPathTemplateValues().get("id"));
- CollectionsHandler.CollectionOperation.DELETESTATUS_OP.execute(req, rsp,
collectionsHandler);
+ final Map<String, Object> v1Params = Maps.newHashMap();
+ v1Params.put(ACTION, DELETESTATUS.lowerName);
+ v1Params.put(REQUESTID, req.getPathTemplateValues().get("id"));
+ collectionsHandler.handleRequestBody(wrapParams(req, v1Params), rsp);
}
@EndPoint(method = DELETE,
@@ -116,7 +120,8 @@ public class ClusterAPI {
path = "/cluster/configs",
permission = CONFIG_READ_PERM)
public void listConfigSet(SolrQueryRequest req, SolrQueryResponse rsp)
throws Exception {
- ConfigSetsHandler.ConfigSetOperation.LIST_OP.call(req, rsp,
configSetsHandler);
+ req = wrapParams(req, "action",
ConfigSetParams.ConfigSetAction.LIST.toString());
+ configSetsHandler.handleRequestBody(req, rsp);
}
@EndPoint(method = POST,
@@ -129,7 +134,7 @@ public class ClusterAPI {
@SuppressWarnings("unchecked")
public void create(PayloadObj<CreateConfigPayload> obj) throws Exception {
Map<String, Object> mapVals = obj.get().toMap(new HashMap<>());
- Map<String,Object> customProps = (Map<String, Object>)
mapVals.remove("properties");
+ Map<String,Object> customProps = obj.get().properties;
if(customProps!= null) {
customProps.forEach((k, o) ->
mapVals.put(ConfigSetCmds.CONFIG_SET_PROPERTY_PREFIX + k, o));
}
@@ -189,8 +194,10 @@ public class ClusterAPI {
path = "/cluster/command-status/{id}",
permission = COLL_READ_PERM)
public void getCommandStatus(SolrQueryRequest req, SolrQueryResponse rsp)
throws Exception {
- wrapParams(req, REQUESTID, req.getPathTemplateValues().get("id"));
- CollectionsHandler.CollectionOperation.REQUESTSTATUS_OP.execute(req, rsp,
collectionsHandler);
+ final Map<String, Object> v1Params = Maps.newHashMap();
+ v1Params.put(ACTION, REQUESTSTATUS.lowerName);
+ v1Params.put(REQUESTID, req.getPathTemplateValues().get("id"));
+ collectionsHandler.handleRequestBody(wrapParams(req, v1Params), rsp);
}
@EndPoint(method = GET,
diff --git a/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java
b/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java
index 1b1abf1..a071d0a 100644
--- a/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java
@@ -17,6 +17,7 @@
package org.apache.solr.handler;
+import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.solr.api.Command;
import org.apache.solr.api.EndPoint;
@@ -76,7 +77,9 @@ public class CollectionsAPI {
method = GET,
permission = COLL_READ_PERM)
public void getCollections(SolrQueryRequest req, SolrQueryResponse rsp)
throws Exception {
- CollectionsHandler.CollectionOperation.LIST_OP.execute(req, rsp,
collectionsHandler);
+ final Map<String, Object> v1Params = Maps.newHashMap();
+ v1Params.put(ACTION, CollectionAction.LIST.toLower());
+ collectionsHandler.handleRequestBody(wrapParams(req, v1Params), rsp);
}
@EndPoint(
diff --git
a/solr/core/src/test/org/apache/solr/handler/V2ClusterAPIMappingTest.java
b/solr/core/src/test/org/apache/solr/handler/V2ClusterAPIMappingTest.java
new file mode 100644
index 0000000..e9a8cd1
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/handler/V2ClusterAPIMappingTest.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.handler;
+
+import com.google.common.collect.Maps;
+import org.apache.solr.api.Api;
+import org.apache.solr.api.ApiBag;
+import org.apache.solr.cloud.ConfigSetCmds;
+import org.apache.solr.common.params.CollectionParams;
+import org.apache.solr.common.params.ConfigSetParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.CommandOperation;
+import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.handler.admin.CollectionsHandler;
+import org.apache.solr.handler.admin.ConfigSetsHandler;
+import org.apache.solr.request.LocalSolrQueryRequest;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static
org.apache.solr.cloud.api.collections.CollectionHandlingUtils.REQUESTID;
+import static org.apache.solr.common.params.CommonParams.ACTION;
+import static org.apache.solr.common.params.CommonParams.NAME;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+/**
+ * Unit tests for the v2 to v1 API mappings found in {@link ClusterAPI}
+ */
+public class V2ClusterAPIMappingTest {
+ private ApiBag apiBag;
+ private ArgumentCaptor<SolrQueryRequest> queryRequestCaptor;
+ private CollectionsHandler mockCollectionsHandler;
+ private ConfigSetsHandler mockConfigSetHandler;
+
+ @BeforeClass
+ public static void ensureWorkingMockito() {
+ assumeWorkingMockito();
+ }
+
+ @Before
+ public void setupApiBag() throws Exception {
+ mockCollectionsHandler = mock(CollectionsHandler.class);
+ mockConfigSetHandler = mock(ConfigSetsHandler.class);
+ queryRequestCaptor = ArgumentCaptor.forClass(SolrQueryRequest.class);
+
+ apiBag = new ApiBag(false);
+ final ClusterAPI clusterAPI = new ClusterAPI(mockCollectionsHandler,
mockConfigSetHandler);
+ apiBag.registerObject(clusterAPI);
+ apiBag.registerObject(clusterAPI.commands);
+ apiBag.registerObject(clusterAPI.configSetCommands);
+ }
+
+ @Test
+ public void testAsyncCommandStatusAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedV1Params("/cluster/command-status/someId", "GET", null);
+
+ assertEquals(CollectionParams.CollectionAction.REQUESTSTATUS.lowerName,
v1Params.get(ACTION));
+ assertEquals("someId", v1Params.get(REQUESTID));
+ }
+
+ @Test
+ public void testClusterAliasesAllParams() throws Exception {
+ final SolrParams v1Params = captureConvertedV1Params("/cluster/aliases",
"GET", null);
+
+ assertEquals(CollectionParams.CollectionAction.LISTALIASES.lowerName,
v1Params.get(ACTION));
+ }
+
+ @Test
+ public void testClusterOverseerAllParams() throws Exception {
+ final SolrParams v1Params = captureConvertedV1Params("/cluster/overseer",
"GET", null);
+
+ assertEquals(CollectionParams.CollectionAction.OVERSEERSTATUS.lowerName,
v1Params.get(ACTION));
+ }
+
+ @Test
+ public void testListClusterAllParams() throws Exception {
+ final SolrParams v1Params = captureConvertedV1Params("/cluster", "GET",
null);
+
+ assertEquals(CollectionParams.CollectionAction.LIST.lowerName,
v1Params.get(ACTION));
+ }
+
+ @Test
+ public void testDeleteCommandStatusAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedV1Params("/cluster/command-status/someId", "DELETE", null);
+
+ assertEquals(CollectionParams.CollectionAction.DELETESTATUS.lowerName,
v1Params.get(ACTION));
+ assertEquals("someId", v1Params.get(REQUESTID));
+ }
+
+ // TODO This should probably really get its own class.
+ @Test
+ public void testDeleteConfigetAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedConfigsetV1Params("/cluster/configs/someConfigset", "DELETE",
null);
+
+ assertEquals(ConfigSetParams.ConfigSetAction.DELETE.toString(),
v1Params.get(ACTION));
+ assertEquals("someConfigset", v1Params.get(NAME));
+ }
+
+ @Test
+ public void testListConfigsetsAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedConfigsetV1Params("/cluster/configs", "GET", null);
+
+ assertEquals(ConfigSetParams.ConfigSetAction.LIST.toString(),
v1Params.get(ACTION));
+ }
+
+ @Test
+ public void testCreateConfigsetAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedConfigsetV1Params("/cluster/configs", "POST",
+ "{'create': {" +
+ "'name': 'new_configset_name', " +
+ "'baseConfigSet':'some_existing_configset', " +
+ "'properties': {'prop1': 'val1', 'prop2': 'val2'}}}");
+
+ assertEquals(ConfigSetParams.ConfigSetAction.CREATE.toString(),
v1Params.get(ACTION));
+ assertEquals("new_configset_name", v1Params.get(NAME));
+ assertEquals("some_existing_configset",
v1Params.get(ConfigSetCmds.BASE_CONFIGSET));
+ assertEquals("val1", v1Params.get("configSetProp.prop1"));
+ assertEquals("val2", v1Params.get("configSetProp.prop2"));
+ }
+
+ @Test
+ public void testUploadConfigsetAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedConfigsetV1Params("/cluster/configs/someConfigSetName", "PUT",
null);
+
+ assertEquals(ConfigSetParams.ConfigSetAction.UPLOAD.toString(),
v1Params.get(ACTION));
+ assertEquals("someConfigSetName", v1Params.get(NAME));
+ // Why does ClusterAPI set the values below as defaults? They disagree
with the v1 defaults in
+ // ConfigSetsHandler.handleConfigUploadRequest
+ assertEquals(true, v1Params.getPrimitiveBool(ConfigSetParams.OVERWRITE));
+ assertEquals(false, v1Params.getPrimitiveBool(ConfigSetParams.CLEANUP));
+ }
+
+ @Test
+ public void testAddFileToConfigsetAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedConfigsetV1Params("/cluster/configs/someConfigSetName/some/file/path",
"PUT", null);
+
+ assertEquals(ConfigSetParams.ConfigSetAction.UPLOAD.toString(),
v1Params.get(ACTION));
+ assertEquals("someConfigSetName", v1Params.get(NAME));
+ assertEquals("/some/file/path", v1Params.get(ConfigSetParams.FILE_PATH));
// Note the leading '/' that makes the path appear absolute
+ assertEquals(true, v1Params.getPrimitiveBool(ConfigSetParams.OVERWRITE));
+ assertEquals(false, v1Params.getPrimitiveBool(ConfigSetParams.CLEANUP));
+ }
+
+ @Test
+ public void testAddRoleAllParams() throws Exception {
+ final SolrParams v1Params = captureConvertedV1Params("/cluster", "POST",
+ "{'add-role': {" +
+ "'node': 'some_node_name', " +
+ "'role':'some_role'}}");
+
+ assertEquals(CollectionParams.CollectionAction.ADDROLE.toString(),
v1Params.get(ACTION));
+ assertEquals("some_node_name", v1Params.get("node"));
+ assertEquals("some_role", v1Params.get("role"));
+ }
+
+ @Test
+ public void testRemoveRoleAllParams() throws Exception {
+ final SolrParams v1Params = captureConvertedV1Params("/cluster", "POST",
+ "{'remove-role': {" +
+ "'node': 'some_node_name', " +
+ "'role':'some_role'}}");
+
+ assertEquals(CollectionParams.CollectionAction.REMOVEROLE.toString(),
v1Params.get(ACTION));
+ assertEquals("some_node_name", v1Params.get("node"));
+ assertEquals("some_role", v1Params.get("role"));
+ }
+
+ @Test
+ public void testSetPropertyAllParams() throws Exception {
+ final SolrParams v1Params = captureConvertedV1Params("/cluster", "POST",
+ "{'set-property': {" +
+ "'name': 'some_prop_name', " +
+ "'val':'some_value'}}");
+
+ assertEquals(CollectionParams.CollectionAction.CLUSTERPROP.toString(),
v1Params.get(ACTION));
+ assertEquals("some_prop_name", v1Params.get(NAME));
+ assertEquals("some_value", v1Params.get("val"));
+ }
+
+ private SolrParams captureConvertedV1Params(String path, String method,
String v2RequestBody) throws Exception {
+ return doCaptureParams(path, method, v2RequestBody,
mockCollectionsHandler);
+ }
+
+ private SolrParams captureConvertedConfigsetV1Params(String path, String
method, String v2RequestBody) throws Exception {
+ return doCaptureParams(path, method, v2RequestBody, mockConfigSetHandler);
+ }
+
+ private SolrParams doCaptureParams(String path, String method, String
v2RequestBody, RequestHandlerBase mockHandler) throws Exception {
+ final HashMap<String, String> parts = new HashMap<>();
+ final Api api = apiBag.lookup(path, method, parts);
+ final SolrQueryResponse rsp = new SolrQueryResponse();
+ final LocalSolrQueryRequest req = new LocalSolrQueryRequest(null,
Maps.newHashMap()) {
+ @Override
+ public List<CommandOperation> getCommands(boolean validateInput) {
+ if (v2RequestBody == null) return Collections.emptyList();
+ return ApiBag.getCommandOperations(new
ContentStreamBase.StringStream(v2RequestBody), api.getCommandSchema(), true);
+ }
+
+ @Override
+ public Map<String, String> getPathTemplateValues() {
+ return parts;
+ }
+
+ @Override
+ public String getHttpMethod() {
+ return method;
+ }
+ };
+
+
+ api.call(req, rsp);
+ verify(mockHandler).handleRequestBody(queryRequestCaptor.capture(), any());
+ return queryRequestCaptor.getValue().getParams();
+ }
+}
diff --git
a/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java
b/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java
index 689073c..a2b0c85 100644
---
a/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java
+++
b/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java
@@ -132,6 +132,13 @@ public class V2CollectionsAPIMappingTest extends
SolrTestCaseJ4 {
}
@Test
+ public void testListCollectionsAllProperties() throws Exception {
+ final SolrParams v1Params = captureConvertedV1Params("/collections",
"GET", null);
+
+ assertEquals(CollectionParams.CollectionAction.LIST.lowerName,
v1Params.get(ACTION));
+ }
+
+ @Test
public void testCreateAliasAllProperties() throws Exception {
final SolrParams v1Params = captureConvertedV1Params("/collections",
"POST",
"{'create-alias': {" +