mirror of https://github.com/apache/lucene.git
SOLR-14871 Use Annotations for v2 APIs in/cluster path (#1878)
This commit is contained in:
parent
9b9b0a6339
commit
7b8e72e553
|
@ -37,7 +37,11 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
import org.apache.solr.client.solrj.SolrRequest;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SpecProvider;
|
||||
import org.apache.solr.common.util.*;
|
||||
import org.apache.solr.common.util.CommandOperation;
|
||||
import org.apache.solr.common.util.ContentStream;
|
||||
import org.apache.solr.common.util.JsonSchemaCreator;
|
||||
import org.apache.solr.common.util.Utils;
|
||||
import org.apache.solr.common.util.ValidatingJsonMap;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.security.AuthorizationContext;
|
||||
|
@ -267,6 +271,7 @@ public class AnnotatedApi extends Api implements PermissionNameProvider , Closea
|
|||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void invoke(SolrQueryRequest req, SolrQueryResponse rsp, CommandOperation cmd) {
|
||||
Object original = null;
|
||||
try {
|
||||
Object o = null;
|
||||
String commandName = null;
|
||||
|
@ -282,12 +287,13 @@ public class AnnotatedApi extends Api implements PermissionNameProvider , Closea
|
|||
}
|
||||
} else {
|
||||
commandName = cmd.name;
|
||||
o = cmd.getCommandData();
|
||||
original = cmd.getCommandData();
|
||||
o = original;
|
||||
if (o instanceof Map && parameterClass != null && parameterClass != Map.class) {
|
||||
o = mapper.readValue(Utils.toJSONString(o), parameterClass);
|
||||
}
|
||||
}
|
||||
PayloadObj<Object> payloadObj = new PayloadObj<>(commandName, o, o, req, rsp);
|
||||
PayloadObj<Object> payloadObj = new PayloadObj<>(commandName, original, o, req, rsp);
|
||||
cmd = payloadObj;
|
||||
method.invoke(obj, payloadObj);
|
||||
checkForErrorInPayload(cmd);
|
||||
|
|
|
@ -31,8 +31,8 @@ public class PayloadObj<T> extends CommandOperation {
|
|||
final SolrQueryRequest req;
|
||||
final SolrQueryResponse rsp;
|
||||
|
||||
public PayloadObj(String operationName, Object metaData, T obj, SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
super(operationName, metaData);
|
||||
public PayloadObj(String operationName, Object originalMetadata, T obj, SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
super(operationName, originalMetadata);
|
||||
this.obj = obj;
|
||||
this.req = req;
|
||||
this.rsp = rsp;
|
||||
|
|
|
@ -87,6 +87,7 @@ import org.apache.solr.core.DirectoryFactory.DirContext;
|
|||
import org.apache.solr.core.backup.repository.BackupRepository;
|
||||
import org.apache.solr.core.backup.repository.BackupRepositoryFactory;
|
||||
import org.apache.solr.filestore.PackageStoreAPI;
|
||||
import org.apache.solr.handler.ClusterAPI;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.handler.SnapShooter;
|
||||
import org.apache.solr.handler.admin.CollectionsHandler;
|
||||
|
@ -719,6 +720,9 @@ public class CoreContainer {
|
|||
createHandler(ZK_PATH, ZookeeperInfoHandler.class.getName(), ZookeeperInfoHandler.class);
|
||||
createHandler(ZK_STATUS_PATH, ZookeeperStatusHandler.class.getName(), ZookeeperStatusHandler.class);
|
||||
collectionsHandler = createHandler(COLLECTIONS_HANDLER_PATH, cfg.getCollectionsHandlerClass(), CollectionsHandler.class);
|
||||
ClusterAPI clusterAPI = new ClusterAPI(collectionsHandler);
|
||||
containerHandlers.getApiBag().registerObject(clusterAPI);
|
||||
containerHandlers.getApiBag().registerObject(clusterAPI.commands);
|
||||
/*
|
||||
* HealthCheckHandler needs to be initialized before InfoHandler, since the later one will call CoreContainer.getHealthCheckHandler().
|
||||
* We don't register the handler here because it'll be registered inside InfoHandler
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* 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 java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.solr.api.Command;
|
||||
import org.apache.solr.api.EndPoint;
|
||||
import org.apache.solr.api.PayloadObj;
|
||||
import org.apache.solr.client.solrj.request.beans.ClusterPropInfo;
|
||||
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.DefaultSolrParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.common.util.ReflectMapWriter;
|
||||
import org.apache.solr.common.util.Utils;
|
||||
import org.apache.solr.core.CoreContainer;
|
||||
import org.apache.solr.handler.admin.CollectionsHandler;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
|
||||
import static org.apache.solr.client.solrj.SolrRequest.METHOD.DELETE;
|
||||
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.cloud.api.collections.OverseerCollectionMessageHandler.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.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
|
||||
import static org.apache.solr.security.PermissionNameProvider.Name.COLL_READ_PERM;
|
||||
|
||||
public class ClusterAPI {
|
||||
private final CoreContainer coreContainer;
|
||||
private final CollectionsHandler collectionsHandler;
|
||||
|
||||
public final Commands commands = new Commands();
|
||||
|
||||
public ClusterAPI(CollectionsHandler ch) {
|
||||
this.collectionsHandler = ch;
|
||||
this.coreContainer = ch.getCoreContainer();
|
||||
}
|
||||
|
||||
|
||||
@EndPoint(method = GET,
|
||||
path = "/cluster/overseer",
|
||||
permission = COLL_READ_PERM)
|
||||
public void getOverseerStatus(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
|
||||
coreContainer.getCollectionsHandler().handleRequestBody(wrapParams(req, "action", OVERSEERSTATUS.toString()), 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, coreContainer.getCollectionsHandler());
|
||||
}
|
||||
|
||||
@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, coreContainer.getCollectionsHandler());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public static SolrQueryRequest wrapParams(SolrQueryRequest req, Object... def) {
|
||||
Map m = Utils.makeMap(def);
|
||||
return wrapParams(req, m);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static SolrQueryRequest wrapParams(SolrQueryRequest req, Map m) {
|
||||
ModifiableSolrParams solrParams = new ModifiableSolrParams();
|
||||
m.forEach((k, v) -> {
|
||||
if(v == null) return;
|
||||
solrParams.add(k.toString(), String.valueOf(v));
|
||||
});
|
||||
DefaultSolrParams dsp = new DefaultSolrParams(req.getParams(),solrParams);
|
||||
req.setParams(dsp);
|
||||
return req;
|
||||
}
|
||||
|
||||
@EndPoint(method = GET,
|
||||
path = "/cluster/command-status",
|
||||
permission = COLL_READ_PERM)
|
||||
public void getCommandStatus(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
|
||||
CollectionsHandler.CollectionOperation.REQUESTSTATUS_OP.execute(req, rsp, collectionsHandler);
|
||||
}
|
||||
|
||||
@EndPoint(method = GET,
|
||||
path = "/cluster/nodes",
|
||||
permission = COLL_READ_PERM)
|
||||
public void getNodes(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
rsp.add("nodes", coreContainer.getZkController().getClusterState().getLiveNodes());
|
||||
}
|
||||
|
||||
@EndPoint(method = POST,
|
||||
path = "/cluster",
|
||||
permission = COLL_EDIT_PERM)
|
||||
public class Commands {
|
||||
|
||||
|
||||
@Command(name = "add-role")
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void addRole(PayloadObj<RoleInfo> obj) throws Exception {
|
||||
RoleInfo info = obj.get();
|
||||
Map m = info.toMap(new HashMap<>());
|
||||
m.put("action", ADDROLE.toString());
|
||||
collectionsHandler.handleRequestBody(wrapParams(obj.getRequest(), m), obj.getResponse());
|
||||
}
|
||||
|
||||
@Command(name = "remove-role")
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void removeRole(PayloadObj<RoleInfo> obj) throws Exception {
|
||||
RoleInfo info = obj.get();
|
||||
Map m = info.toMap(new HashMap<>());
|
||||
m.put("action", REMOVEROLE.toString());
|
||||
collectionsHandler.handleRequestBody(wrapParams(obj.getRequest(),m), obj.getResponse());
|
||||
|
||||
}
|
||||
|
||||
@Command(name = "set-obj-property")
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void setObjProperty(PayloadObj<ClusterPropInfo> obj) {
|
||||
//Not using the object directly here because the API differentiate between {name:null} and {}
|
||||
Map m = obj.getDataMap();
|
||||
ClusterProperties clusterProperties = new ClusterProperties(coreContainer.getZkController().getZkClient());
|
||||
try {
|
||||
clusterProperties.setClusterProperties(m);
|
||||
} catch (Exception e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in API", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Command(name = "set-property")
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void setProperty(PayloadObj<Map<String,String>> obj) throws Exception {
|
||||
Map m = obj.get();
|
||||
m.put("action", CLUSTERPROP.toString());
|
||||
collectionsHandler.handleRequestBody(wrapParams(obj.getRequest(),m ), obj.getResponse());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class RoleInfo implements ReflectMapWriter {
|
||||
@JsonProperty(required = true)
|
||||
public String node;
|
||||
@JsonProperty(required = true)
|
||||
public String role;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -60,6 +60,7 @@ import org.apache.solr.common.params.SolrParams;
|
|||
import org.apache.solr.common.util.CommandOperation;
|
||||
import org.apache.solr.common.util.ExecutorUtil;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SolrNamedThreadFactory;
|
||||
import org.apache.solr.common.util.StrUtils;
|
||||
import org.apache.solr.common.util.Utils;
|
||||
import org.apache.solr.core.ConfigOverlay;
|
||||
|
@ -76,7 +77,6 @@ import org.apache.solr.response.SolrQueryResponse;
|
|||
import org.apache.solr.schema.SchemaManager;
|
||||
import org.apache.solr.security.AuthorizationContext;
|
||||
import org.apache.solr.security.PermissionNameProvider;
|
||||
import org.apache.solr.common.util.SolrNamedThreadFactory;
|
||||
import org.apache.solr.util.RTimer;
|
||||
import org.apache.solr.util.SolrPluginUtils;
|
||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package org.apache.solr.handler.admin;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
|
@ -28,18 +27,11 @@ import org.apache.solr.client.solrj.request.CollectionApiMapping;
|
|||
import org.apache.solr.client.solrj.request.CollectionApiMapping.CommandMeta;
|
||||
import org.apache.solr.client.solrj.request.CollectionApiMapping.Meta;
|
||||
import org.apache.solr.client.solrj.request.CollectionApiMapping.V2EndPoint;
|
||||
import org.apache.solr.common.Callable;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.cloud.ClusterProperties;
|
||||
import org.apache.solr.common.util.CommandOperation;
|
||||
import org.apache.solr.handler.admin.CollectionsHandler.CollectionOperation;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CollectionHandlerApi extends BaseHandlerApiSupport {
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
final CollectionsHandler handler;
|
||||
static Collection<ApiCommand> apiCommands = createCollMapping();
|
||||
|
@ -64,55 +56,10 @@ public class CollectionHandlerApi extends BaseHandlerApiSupport {
|
|||
}
|
||||
}
|
||||
}
|
||||
//The following APIs have only V2 implementations
|
||||
addApi(result, Meta.GET_NODES, params -> params.rsp.add("nodes", ((CollectionHandlerApi) params.apiHandler).handler.coreContainer.getZkController().getClusterState().getLiveNodes()));
|
||||
addApi(result, Meta.SET_CLUSTER_PROPERTY_OBJ, params -> {
|
||||
List<CommandOperation> commands = params.req.getCommands(true);
|
||||
if (commands == null || commands.isEmpty()) throw new RuntimeException("Empty commands");
|
||||
ClusterProperties clusterProperties = new ClusterProperties(((CollectionHandlerApi) params.apiHandler).handler.coreContainer.getZkController().getZkClient());
|
||||
|
||||
try {
|
||||
clusterProperties.setClusterProperties(commands.get(0).getDataMap());
|
||||
} catch (Exception e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in API", e);
|
||||
}
|
||||
});
|
||||
|
||||
for (Meta meta : Meta.values()) {
|
||||
if (result.get(meta) == null) {
|
||||
log.error("ERROR_INIT. No corresponding API implementation for : {}", meta.commandName);
|
||||
}
|
||||
}
|
||||
|
||||
return result.values();
|
||||
}
|
||||
|
||||
private static void addApi(Map<Meta, ApiCommand> result, Meta metaInfo, Callable<ApiParams> fun) {
|
||||
result.put(metaInfo, new ApiCommand() {
|
||||
@Override
|
||||
public CommandMeta meta() {
|
||||
return metaInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(SolrQueryRequest req, SolrQueryResponse rsp, BaseHandlerApiSupport apiHandler) throws Exception {
|
||||
fun.call(new ApiParams(req, rsp, apiHandler));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static class ApiParams {
|
||||
final SolrQueryRequest req;
|
||||
final SolrQueryResponse rsp;
|
||||
final BaseHandlerApiSupport apiHandler;
|
||||
|
||||
ApiParams(SolrQueryRequest req, SolrQueryResponse rsp, BaseHandlerApiSupport apiHandler) {
|
||||
this.req = req;
|
||||
this.rsp = rsp;
|
||||
this.apiHandler = apiHandler;
|
||||
}
|
||||
}
|
||||
|
||||
public CollectionHandlerApi(CollectionsHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,24 @@
|
|||
*/
|
||||
package org.apache.solr.handler.admin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -83,24 +101,6 @@ import org.apache.zookeeper.KeeperException;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.solr.client.solrj.response.RequestStatusState.COMPLETED;
|
||||
import static org.apache.solr.client.solrj.response.RequestStatusState.FAILED;
|
||||
import static org.apache.solr.client.solrj.response.RequestStatusState.NOT_FOUND;
|
||||
|
@ -223,17 +223,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
|||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
|
||||
// Make sure the cores is enabled
|
||||
CoreContainer cores = getCoreContainer();
|
||||
if (cores == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
|
||||
"Core container instance missing");
|
||||
}
|
||||
|
||||
// Make sure that the core is ZKAware
|
||||
if (!cores.isZooKeeperAware()) {
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST,
|
||||
"Solr instance is not running in SolrCloud mode.");
|
||||
}
|
||||
CoreContainer cores = checkErrors();
|
||||
|
||||
// Pick the action
|
||||
SolrParams params = req.getParams();
|
||||
|
@ -256,6 +246,21 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
|||
rsp.setHttpCaching(false);
|
||||
}
|
||||
|
||||
protected CoreContainer checkErrors() {
|
||||
CoreContainer cores = getCoreContainer();
|
||||
if (cores == null) {
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST,
|
||||
"Core container instance missing");
|
||||
}
|
||||
|
||||
// Make sure that the core is ZKAware
|
||||
if (!cores.isZooKeeperAware()) {
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST,
|
||||
"Solr instance is not running in SolrCloud mode.");
|
||||
}
|
||||
return cores;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void invokeAction(SolrQueryRequest req, SolrQueryResponse rsp, CoreContainer cores, CollectionAction action, CollectionOperation operation) throws Exception {
|
||||
if (!coreContainer.isZooKeeperAware()) {
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.apache.solr.common.MapSerializable;
|
|||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.common.cloud.SolrClassLoader;
|
||||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.common.params.MapSolrParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
|
@ -62,7 +63,6 @@ import org.apache.solr.common.util.Cache;
|
|||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.Pair;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.apache.solr.common.cloud.SolrClassLoader;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.apache.solr.core.XmlConfigFile;
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.apache.solr.common.util.ContentStreamBase;
|
|||
import org.apache.solr.common.util.Pair;
|
||||
import org.apache.solr.common.util.Utils;
|
||||
import org.apache.solr.core.CoreContainer;
|
||||
import org.apache.solr.handler.ClusterAPI;
|
||||
import org.apache.solr.request.LocalSolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
|
@ -84,6 +85,10 @@ public class TestCollectionAPIs extends SolrTestCaseJ4 {
|
|||
apiBag = new ApiBag(false);
|
||||
Collection<Api> apis = collectionsHandler.getApis();
|
||||
for (Api api : apis) apiBag.register(api, Collections.emptyMap());
|
||||
|
||||
ClusterAPI clusterAPI = new ClusterAPI(collectionsHandler);
|
||||
apiBag.registerObject(clusterAPI);
|
||||
apiBag.registerObject(clusterAPI.commands);
|
||||
}
|
||||
//test a simple create collection call
|
||||
compareOutput(apiBag, "/collections", POST,
|
||||
|
@ -277,6 +282,11 @@ public class TestCollectionAPIs extends SolrTestCaseJ4 {
|
|||
MockCollectionsHandler() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CoreContainer checkErrors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void copyFromClusterProp(Map<String, Object> props, String prop) {
|
||||
|
||||
|
|
|
@ -41,12 +41,7 @@ import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
|
|||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.ConfigSetEndPoint.CONFIG_COMMANDS;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.ConfigSetEndPoint.CONFIG_DEL;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.ConfigSetEndPoint.LIST_CONFIG;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.CLUSTER;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.CLUSTER_ALIASES;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.CLUSTER_CMD;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.CLUSTER_CMD_STATUS;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.CLUSTER_CMD_STATUS_DELETE;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.CLUSTER_NODES;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.COLLECTIONS;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.COLLECTIONS_COMMANDS;
|
||||
import static org.apache.solr.client.solrj.request.CollectionApiMapping.EndPoint.COLLECTION_STATE;
|
||||
|
@ -66,10 +61,6 @@ public class CollectionApiMapping {
|
|||
|
||||
public enum Meta implements CommandMeta {
|
||||
GET_COLLECTIONS(COLLECTIONS, GET, LIST),
|
||||
GET_CLUSTER(CLUSTER, GET, LIST, "/cluster", null),
|
||||
GET_CLUSTER_OVERSEER(CLUSTER, GET, OVERSEERSTATUS, "/cluster/overseer", null),
|
||||
GET_CLUSTER_STATUS_CMD(CLUSTER_CMD_STATUS, GET, REQUESTSTATUS),
|
||||
DELETE_CLUSTER_STATUS(CLUSTER_CMD_STATUS_DELETE, DELETE, DELETESTATUS),
|
||||
GET_A_COLLECTION(COLLECTION_STATE, GET, CLUSTERSTATUS),
|
||||
LIST_ALIASES(CLUSTER_ALIASES, GET, LISTALIASES),
|
||||
CREATE_COLLECTION(COLLECTIONS_COMMANDS,
|
||||
|
@ -190,23 +181,23 @@ public class CollectionApiMapping {
|
|||
NAME, "collection",
|
||||
"propertyName", "name",
|
||||
"propertyValue", "value")),
|
||||
ADD_ROLE(CLUSTER_CMD,
|
||||
/* ADD_ROLE(CLUSTER_CMD,
|
||||
POST,
|
||||
ADDROLE,
|
||||
"add-role",null),
|
||||
REMOVE_ROLE(CLUSTER_CMD,
|
||||
"add-role",null),*/
|
||||
/* REMOVE_ROLE(CLUSTER_CMD,
|
||||
POST,
|
||||
REMOVEROLE,
|
||||
"remove-role",null),
|
||||
"remove-role",null),*/
|
||||
|
||||
SET_CLUSTER_PROPERTY(CLUSTER_CMD,
|
||||
/* SET_CLUSTER_PROPERTY(CLUSTER_CMD,
|
||||
POST,
|
||||
CLUSTERPROP,
|
||||
"set-property",null),
|
||||
SET_CLUSTER_PROPERTY_OBJ(CLUSTER_CMD,
|
||||
"set-property",null),*/
|
||||
/* SET_CLUSTER_PROPERTY_OBJ(CLUSTER_CMD,
|
||||
POST,
|
||||
null,
|
||||
"set-obj-property", null),
|
||||
"set-obj-property", null),*/
|
||||
BACKUP_COLLECTION(COLLECTIONS_COMMANDS,
|
||||
POST,
|
||||
BACKUP,
|
||||
|
@ -218,7 +209,6 @@ public class CollectionApiMapping {
|
|||
"restore-collection",
|
||||
null
|
||||
),
|
||||
GET_NODES(CLUSTER_NODES, GET, null),
|
||||
FORCE_LEADER(PER_COLLECTION_PER_SHARD_COMMANDS, POST, CollectionAction.FORCELEADER, "force-leader", null),
|
||||
BALANCE_SHARD_UNIQUE(PER_COLLECTION, POST, BALANCESHARDUNIQUE,"balance-shard-unique" , null)
|
||||
;
|
||||
|
@ -342,12 +332,7 @@ public class CollectionApiMapping {
|
|||
}
|
||||
|
||||
public enum EndPoint implements V2EndPoint {
|
||||
CLUSTER("cluster"),
|
||||
CLUSTER_ALIASES("cluster.aliases"),
|
||||
CLUSTER_CMD("cluster.Commands"),
|
||||
CLUSTER_NODES("cluster.nodes"),
|
||||
CLUSTER_CMD_STATUS("cluster.commandstatus"),
|
||||
CLUSTER_CMD_STATUS_DELETE("cluster.commandstatus.delete"),
|
||||
COLLECTIONS_COMMANDS("collections.Commands"),
|
||||
COLLECTIONS("collections"),
|
||||
COLLECTION_STATE("collections.collection"),
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.client.solrj.request.beans;
|
||||
|
||||
import org.apache.solr.common.annotation.JsonProperty;
|
||||
import org.apache.solr.common.util.ReflectMapWriter;
|
||||
|
||||
public class ClusterPropInfo implements ReflectMapWriter {
|
||||
|
||||
@JsonProperty
|
||||
public String urlScheme;
|
||||
|
||||
@JsonProperty
|
||||
public Integer maxCoresPerNode;
|
||||
@JsonProperty
|
||||
public String location;
|
||||
|
||||
@JsonProperty
|
||||
public DefaultsInfo defaults;
|
||||
|
||||
@JsonProperty
|
||||
public CollectionDefaults collectionDefaults;
|
||||
|
||||
public static class CollectionDefaults implements ReflectMapWriter {
|
||||
@JsonProperty
|
||||
public Integer numShards;
|
||||
@JsonProperty
|
||||
public Integer tlogReplicas;
|
||||
@JsonProperty
|
||||
public Integer pullReplicas;
|
||||
@JsonProperty
|
||||
public Integer nrtReplicas;
|
||||
|
||||
}
|
||||
|
||||
public static class DefaultsInfo implements ReflectMapWriter {
|
||||
|
||||
@JsonProperty
|
||||
public CollectionDefaults collection;
|
||||
|
||||
@JsonProperty
|
||||
public CollectionDefaults cluster;
|
||||
|
||||
}
|
||||
|
||||
public static class ClusterInfo implements ReflectMapWriter {
|
||||
@JsonProperty
|
||||
public Boolean useLegacyReplicaAssignment;
|
||||
|
||||
|
||||
@JsonProperty
|
||||
public CollectionDefaults collection;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -27,7 +27,7 @@ public class DefaultSolrParams extends SolrParams {
|
|||
protected final SolrParams params;
|
||||
protected final SolrParams defaults;
|
||||
|
||||
protected DefaultSolrParams(SolrParams params, SolrParams defaults) {
|
||||
public DefaultSolrParams(SolrParams params, SolrParams defaults) {
|
||||
assert params != null && defaults != null;
|
||||
this.params = params;
|
||||
this.defaults = defaults;
|
||||
|
|
|
@ -58,10 +58,16 @@ public class JsonSchemaCreator {
|
|||
private static Map<String, Object> createSchemaFromType(java.lang.reflect.Type t, Map<String, Object> map) {
|
||||
if (natives.containsKey(t)) {
|
||||
map.put("type", natives.get(t));
|
||||
} else if (t instanceof ParameterizedType && ((ParameterizedType) t).getRawType() == List.class) {
|
||||
Type typ = ((ParameterizedType) t).getActualTypeArguments()[0];
|
||||
map.put("type", "array");
|
||||
map.put("items", getSchema(typ));
|
||||
} else if (t instanceof ParameterizedType) {
|
||||
if (((ParameterizedType) t).getRawType() == List.class) {
|
||||
Type typ = ((ParameterizedType) t).getActualTypeArguments()[0];
|
||||
map.put("type", "array");
|
||||
map.put("items", getSchema(typ));
|
||||
} else if (((ParameterizedType) t).getRawType() == Map.class) {
|
||||
Type typ = ((ParameterizedType) t).getActualTypeArguments()[0];
|
||||
map.put("type", "object");
|
||||
map.put("additionalProperties", true);
|
||||
}
|
||||
} else {
|
||||
createObjectSchema((Class) t, map);
|
||||
}
|
||||
|
|
|
@ -871,7 +871,7 @@ public class Utils {
|
|||
l.add((ew, inst) -> ew.put(fname, (float) mh.invoke(inst)));
|
||||
} else {
|
||||
MethodHandle mh = lookup.findGetter(c, field.getName(), field.getType());
|
||||
l.add((ew, inst) -> ew.put(fname, mh.invoke(inst)));
|
||||
l.add((ew, inst) -> ew.putIfNotNull(fname, mh.invoke(inst)));
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
//this is unlikely
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
{
|
||||
"documentation": "https://lucene.apache.org/solr/guide/cluster-node-management.html",
|
||||
"description": "Cluster-wide commands to assign roles to nodes, remove role assignments, or add, edit or remove a cluster-wide property.",
|
||||
"methods": [
|
||||
"POST"
|
||||
],
|
||||
"url": {
|
||||
"paths": [
|
||||
"/cluster"
|
||||
]
|
||||
},
|
||||
"commands": {
|
||||
"add-role":{
|
||||
"type":"object",
|
||||
"documentation":"https://lucene.apache.org/solr/guide/cluster-node-management.html#addrole",
|
||||
"description":"Assign a specific role to a node in the cluster.",
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "The name of the role. The only supported role is 'overseer'."
|
||||
|
||||
},
|
||||
"node": {
|
||||
"type": "string",
|
||||
"description": "The name of the node. It is possible to assign a role even before that node is started."
|
||||
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"role",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"remove-role":{
|
||||
"type":"object",
|
||||
"documentation":"https://lucene.apache.org/solr/guide/cluster-node-management.html#removerole",
|
||||
"description":"Unassign a role from a node in the cluster.",
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "The name of the role. The only supported role as of now is 'overseer'."
|
||||
|
||||
},
|
||||
"node": {
|
||||
"type": "string",
|
||||
"description": "The name of the node where the role should be removed."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"role",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"set-property": {
|
||||
"type": "object",
|
||||
"documentation": "https://lucene.apache.org/solr/guide/cluster-node-management.html#clusterprop",
|
||||
"description": "Add, edit, or delete a cluster-wide property.",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the property"
|
||||
},
|
||||
"val": {
|
||||
"type": ["string","boolean","null"],
|
||||
"description": "The value of the property. If the value is empty or null, the property is unset."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"val"
|
||||
]
|
||||
},
|
||||
"set-obj-property": {
|
||||
"type": "object",
|
||||
"documentation": "https://lucene.apache.org/solr/guide/cluster-node-management.html#clusterprop",
|
||||
"description": "Add, edit, or delete a cluster-wide property.",
|
||||
"properties": {
|
||||
"urlScheme": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxCoresPerNode": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"defaults" : {
|
||||
"type" : "object",
|
||||
"properties": {
|
||||
"cluster": {
|
||||
"type" : "object",
|
||||
"properties": {
|
||||
"useLegacyReplicaAssignment": {
|
||||
"type" : "boolean",
|
||||
"description" : "Decides wheyher to use the deprecated legacy replica assignment strategy or not"
|
||||
}
|
||||
}
|
||||
},
|
||||
"collection": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"numShards": {
|
||||
"type": "integer",
|
||||
"description": "Default number of shards for a collection"
|
||||
},
|
||||
"tlogReplicas": {
|
||||
"type": "integer",
|
||||
"description": "Default number of TLOG replicas"
|
||||
},
|
||||
"pullReplicas": {
|
||||
"type": "integer",
|
||||
"description": "Default number of PULL replicas"
|
||||
},
|
||||
"nrtReplicas": {
|
||||
"type": "integer",
|
||||
"description": "Default number of NRT replicas"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"collectionDefaults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"numShards": {
|
||||
"type": "integer",
|
||||
"description": "Default number of shards for a collection"
|
||||
},
|
||||
"tlogReplicas": {
|
||||
"type": "integer",
|
||||
"description": "Default number of TLOG replicas"
|
||||
},
|
||||
"pullReplicas": {
|
||||
"type": "integer",
|
||||
"description": "Default number of PULL replicas"
|
||||
},
|
||||
"nrtReplicas": {
|
||||
"type": "integer",
|
||||
"description": "Default number of NRT replicas"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"methods": [
|
||||
"DELETE"
|
||||
],
|
||||
"url": {
|
||||
"paths": [
|
||||
"/cluster/command-status/{id}"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"methods": [
|
||||
"GET"
|
||||
],
|
||||
"url": {
|
||||
"paths": [
|
||||
"/cluster/command-status"
|
||||
],
|
||||
"params": {
|
||||
"flush": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"id":{
|
||||
"type":"string",
|
||||
"description": "The command id"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"documentation": "https://lucene.apache.org/solr/guide/cluster-node-management.html",
|
||||
"description": "General information about the cluster, including defined collections (with the 'cluster' endpoint), status of the overseer (with the 'cluster/overseer' endpoint), and available nodes (with the 'cluster/nodes' endpoint).",
|
||||
"methods": [
|
||||
"GET"
|
||||
],
|
||||
"url": {
|
||||
"paths": [
|
||||
"/cluster",
|
||||
"/cluster/overseer",
|
||||
"/cluster/nodes"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@ public class JsonValidatorTest extends SolrTestCaseJ4 {
|
|||
checkSchema("core.config.Commands");
|
||||
checkSchema("core.SchemaEdit");
|
||||
checkSchema("cluster.configs.Commands");
|
||||
checkSchema("cluster.Commands");
|
||||
// checkSchema("cluster.Commands");
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue