SOLR-9874: CREATEALIAS should fail if target collections don't exist

This commit is contained in:
Tomas Fernandez Lobbe 2016-12-19 16:54:13 -08:00
parent 4d81eee8a1
commit 84bbb8f797
9 changed files with 81 additions and 34 deletions

View File

@ -304,6 +304,8 @@ Other Changes
* SOLR-8959: Refactored TestSegmentSorting out of TestMiniSolrCloudCluster (hossman)
* SOLR-9874: Solr will reject CREATEALIAS requests if target collections don't exist (Tomás Fernández Löbbe)
================== 6.3.0 ==================

View File

@ -91,13 +91,6 @@ public class SolrMorphlineZkAliasTest extends AbstractSolrMorphlineZkTestBase {
Notifications.notifyRollbackTransaction(morphline);
Notifications.notifyShutdown(morphline);
CollectionAdminRequest.createAlias("aliascollection", "collection1,collection2")
.processAndWait(cluster.getSolrClient(), TIMEOUT);
expectThrows(IllegalArgumentException.class, () -> {
parse("test-morphlines" + File.separator + "loadSolrBasic", "aliascollection");
});
}
}

View File

@ -17,8 +17,11 @@
*/
package org.apache.solr.cloud;
import static org.apache.solr.common.params.CommonParams.NAME;
import java.lang.invoke.MethodHandles;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -35,8 +38,6 @@ import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.solr.common.params.CommonParams.NAME;
public class CreateAliasCmd implements Cmd {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@ -52,10 +53,12 @@ public class CreateAliasCmd implements Cmd {
String aliasName = message.getStr(NAME);
String collections = message.getStr("collections");
Map<String, Map<String, String>> newAliasesMap = new HashMap<>();
Map<String, String> newCollectionAliasesMap = new HashMap<>();
ZkStateReader zkStateReader = ocmh.zkStateReader;
Map<String, String> prevColAliases = zkStateReader.getAliases().getCollectionAliasMap();
validateAllCollectionsExist(collections, prevColAliases, zkStateReader.getClusterState());
Map<String, Map<String, String>> newAliasesMap = new HashMap<>();
Map<String, String> newCollectionAliasesMap = new HashMap<>();
if (prevColAliases != null) {
newCollectionAliasesMap.putAll(prevColAliases);
}
@ -81,6 +84,16 @@ public class CreateAliasCmd implements Cmd {
}
}
private void validateAllCollectionsExist(String collections, Map<String,String> prevColAliases, ClusterState clusterState) {
String[] collectionArr = collections.split(",");
for (String collection:collectionArr) {
if (clusterState.getCollectionOrNull(collection) == null && (prevColAliases == null || !prevColAliases.containsKey(collection))) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
String.format(Locale.ROOT, "Can't create collection alias for collections='%s', '%s' is not an existing collection or alias", collections, collection));
}
}
}
private void checkForAlias(String name, String value) {
TimeOut timeout = new TimeOut(30, TimeUnit.SECONDS);

View File

@ -437,7 +437,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
return null;
}),
CREATEALIAS_OP(CREATEALIAS, (req, rsp, h) -> {
final String aliasName = SolrIdentifierValidator.validateAliasName(req.getParams().get(NAME));
SolrIdentifierValidator.validateAliasName(req.getParams().get(NAME));
return req.getParams().required().getAll(null, NAME, "collections");
}),
DELETEALIAS_OP(DELETEALIAS, (req, rsp, h) -> req.getParams().required().getAll(null, NAME)),

View File

@ -16,8 +16,6 @@
*/
package org.apache.solr.cloud;
import java.lang.invoke.MethodHandles;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
@ -28,13 +26,9 @@ import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrException;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AliasIntegrationTest extends SolrCloudTestCase {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@BeforeClass
public static void setupCluster() throws Exception {
configureCluster(2)
@ -160,9 +154,49 @@ public class AliasIntegrationTest extends SolrCloudTestCase {
cluster.getSolrClient().query(q);
});
assertTrue("Unexpected exception message: " + e.getMessage(), e.getMessage().contains("Collection not found: testalias"));
logger.info("### FINISHED ACTUAL TEST");
}
public void testErrorChecks() throws Exception {
CollectionAdminRequest.createCollection("testErrorChecks-collection", "conf", 2, 1).process(cluster.getSolrClient());
waitForState("Expected testErrorChecks-collection to be created with 2 shards and 1 replica", "testErrorChecks-collection", clusterShape(2, 1));
ignoreException(".");
// Invalid Alias name
SolrException e = expectThrows(SolrException.class, () -> {
CollectionAdminRequest.createAlias("test:alias", "testErrorChecks-collection").process(cluster.getSolrClient());
});
assertEquals(SolrException.ErrorCode.BAD_REQUEST, SolrException.ErrorCode.getErrorCode(e.code()));
// Target collection doesn't exists
e = expectThrows(SolrException.class, () -> {
CollectionAdminRequest.createAlias("testalias", "doesnotexist").process(cluster.getSolrClient());
});
assertEquals(SolrException.ErrorCode.BAD_REQUEST, SolrException.ErrorCode.getErrorCode(e.code()));
assertTrue(e.getMessage().contains("Can't create collection alias for collections='doesnotexist', 'doesnotexist' is not an existing collection or alias"));
// One of the target collections doesn't exist
e = expectThrows(SolrException.class, () -> {
CollectionAdminRequest.createAlias("testalias", "testErrorChecks-collection,doesnotexist").process(cluster.getSolrClient());
});
assertEquals(SolrException.ErrorCode.BAD_REQUEST, SolrException.ErrorCode.getErrorCode(e.code()));
assertTrue(e.getMessage().contains("Can't create collection alias for collections='testErrorChecks-collection,doesnotexist', 'doesnotexist' is not an existing collection or alias"));
// Valid
CollectionAdminRequest.createAlias("testalias", "testErrorChecks-collection").process(cluster.getSolrClient());
CollectionAdminRequest.createAlias("testalias2", "testalias").process(cluster.getSolrClient());
// Alias + invalid
e = expectThrows(SolrException.class, () -> {
CollectionAdminRequest.createAlias("testalias3", "testalias2,doesnotexist").process(cluster.getSolrClient());
});
assertEquals(SolrException.ErrorCode.BAD_REQUEST, SolrException.ErrorCode.getErrorCode(e.code()));
unIgnoreException(".");
CollectionAdminRequest.deleteAlias("testalias").process(cluster.getSolrClient());
CollectionAdminRequest.deleteAlias("testalias2").process(cluster.getSolrClient());
CollectionAdminRequest.deleteCollection("testErrorChecks-collection");
}
}

View File

@ -62,16 +62,17 @@ public class JdbcTest extends SolrCloudTestCase {
String collection;
boolean useAlias = random().nextBoolean();
if(useAlias) {
if (useAlias) {
collection = COLLECTIONORALIAS + "_collection";
CollectionAdminRequest.createAlias(COLLECTIONORALIAS, collection).process(cluster.getSolrClient());
} else {
collection = COLLECTIONORALIAS;
}
CollectionAdminRequest.createCollection(collection, "conf", 2, 1).process(cluster.getSolrClient());
AbstractDistribZkTestBase.waitForRecoveriesToFinish(collection, cluster.getSolrClient().getZkStateReader(),
false, true, DEFAULT_TIMEOUT);
if (useAlias) {
CollectionAdminRequest.createAlias(COLLECTIONORALIAS, collection).process(cluster.getSolrClient());
}
new UpdateRequest()
.add(id, "0", "a_s", "hello0", "a_i", "0", "a_f", "1", "testnull_i", null)

View File

@ -62,18 +62,19 @@ public class JDBCStreamTest extends SolrCloudTestCase {
.addConfig("conf", getFile("solrj").toPath().resolve("solr").resolve("configsets").resolve("streaming").resolve("conf"))
.configure();
String collection;
boolean useAlias = random().nextBoolean();
if(useAlias) {
String collection;
if (useAlias) {
collection = COLLECTIONORALIAS + "_collection";
CollectionAdminRequest.createAlias(COLLECTIONORALIAS, collection).process(cluster.getSolrClient());
} else {
collection = COLLECTIONORALIAS;
}
CollectionAdminRequest.createCollection(collection, "conf", 2, 1).process(cluster.getSolrClient());
AbstractDistribZkTestBase.waitForRecoveriesToFinish(collection, cluster.getSolrClient().getZkStateReader(),
false, true, TIMEOUT);
if (useAlias) {
CollectionAdminRequest.createAlias(COLLECTIONORALIAS, collection).process(cluster.getSolrClient());
}
}
@BeforeClass

View File

@ -80,16 +80,17 @@ public class StreamExpressionTest extends SolrCloudTestCase {
String collection;
useAlias = random().nextBoolean();
if(useAlias) {
if (useAlias) {
collection = COLLECTIONORALIAS + "_collection";
CollectionAdminRequest.createAlias(COLLECTIONORALIAS, collection).process(cluster.getSolrClient());
} else {
collection = COLLECTIONORALIAS;
}
CollectionAdminRequest.createCollection(collection, "conf", 2, 1).process(cluster.getSolrClient());
AbstractDistribZkTestBase.waitForRecoveriesToFinish(collection, cluster.getSolrClient().getZkStateReader(),
false, true, TIMEOUT);
if (useAlias) {
CollectionAdminRequest.createAlias(COLLECTIONORALIAS, collection).process(cluster.getSolrClient());
}
}
@Before

View File

@ -94,15 +94,17 @@ public static void configureCluster() throws Exception {
String collection;
useAlias = random().nextBoolean();
if(useAlias) {
if (useAlias) {
collection = COLLECTIONORALIAS + "_collection";
CollectionAdminRequest.createAlias(COLLECTIONORALIAS, collection).process(cluster.getSolrClient());
} else {
collection = COLLECTIONORALIAS;
}
CollectionAdminRequest.createCollection(collection, "conf", numShards, 1).process(cluster.getSolrClient());
AbstractDistribZkTestBase.waitForRecoveriesToFinish(collection, cluster.getSolrClient().getZkStateReader(), false, true, DEFAULT_TIMEOUT);
AbstractDistribZkTestBase.waitForRecoveriesToFinish(collection, cluster.getSolrClient().getZkStateReader(),
false, true, DEFAULT_TIMEOUT);
if (useAlias) {
CollectionAdminRequest.createAlias(COLLECTIONORALIAS, collection).process(cluster.getSolrClient());
}
zkHost = cluster.getZkServer().getZkAddress();
streamFactory.withCollectionZkHost(COLLECTIONORALIAS, zkHost);