SOLR-8725: Allow hyphen in shard, collection, core, and alias names but not the first char

This commit is contained in:
anshum 2016-03-02 16:18:42 -08:00
parent a079ff2528
commit 6de2b7dbd1
9 changed files with 50 additions and 42 deletions

View File

@ -382,6 +382,8 @@ Other Changes
* SOLR-8778: Deprecate CSVStrategy's setters, and make its pre-configured strategies immutable. (Steve Rowe)
* SOLR-8725: Allow hyphen in collection, core, shard, and alias name as the non-first character (Anshum Gupta)
================== 5.5.1 ==================
Bug Fixes

View File

@ -805,8 +805,7 @@ public class CoreContainer {
try {
MDCLoggingContext.setCore(core);
if (!SolrIdentifierValidator.validateCoreName(dcore.getName())) {
throw new SolrException(ErrorCode.BAD_REQUEST, "Invalid core: " + dcore.getName()
+ ". Core names must consist entirely of periods, underscores, and alphanumerics");
throw new SolrException(ErrorCode.BAD_REQUEST, SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.CORE, dcore.getName()));
}
if (zkSys.getZkController() != null) {
zkSys.getZkController().preRegister(dcore);
@ -1010,9 +1009,9 @@ public class CoreContainer {
}
public void rename(String name, String toName) {
if(!SolrIdentifierValidator.validateCoreName(toName)) {
throw new SolrException(ErrorCode.BAD_REQUEST, "Invalid core: " + toName
+ ". Core names must consist entirely of periods, underscores, and alphanumerics");
if (!SolrIdentifierValidator.validateCoreName(toName)) {
throw new SolrException(ErrorCode.BAD_REQUEST, SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.CORE,
toName));
}
try (SolrCore core = getCore(name)) {
if (core != null) {

View File

@ -347,14 +347,12 @@ public class CollectionsHandler extends RequestHandlerBase {
verifyRuleParams(h.coreContainer, props);
final String collectionName = (String) props.get(NAME);
if (!SolrIdentifierValidator.validateCollectionName(collectionName)) {
throw new SolrException(ErrorCode.BAD_REQUEST, "Invalid collection: " + collectionName
+ ". Collection names must consist entirely of periods, underscores, and alphanumerics");
throw new SolrException(ErrorCode.BAD_REQUEST,
SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.COLLECTION, collectionName));
}
final String shardsParam = (String) props.get(SHARDS_PROP);
if (StringUtils.isNotEmpty(shardsParam)) {
log.info("Validating shards param!!!!!!!!" + shardsParam);
verifyShardsParam(shardsParam);
log.info("Validating shards param!!!!!!! done" + shardsParam);
}
if (SYSTEM_COLL.equals(collectionName)) {
//We must always create a .system collection with only a single shard
@ -434,8 +432,7 @@ public class CollectionsHandler extends RequestHandlerBase {
throws Exception {
final String aliasName = req.getParams().get(NAME);
if (!SolrIdentifierValidator.validateCollectionName(aliasName)) {
throw new SolrException(ErrorCode.BAD_REQUEST, "Invalid alias: " + aliasName
+ ". Aliases must consist entirely of periods, underscores, and alphanumerics");
throw new SolrException(ErrorCode.BAD_REQUEST, SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.ALIAS, aliasName));
}
return req.getParams().required().getAll(null, NAME, "collections");
}
@ -502,8 +499,8 @@ public class CollectionsHandler extends RequestHandlerBase {
ClusterState clusterState = handler.coreContainer.getZkController().getClusterState();
final String newShardName = req.getParams().get(SHARD_ID_PROP);
if (!SolrIdentifierValidator.validateShardName(newShardName)) {
throw new SolrException(ErrorCode.BAD_REQUEST, "Invalid shard: " + newShardName
+ ". Shard names must consist entirely of periods, underscores, and alphanumerics");
throw new SolrException(ErrorCode.BAD_REQUEST, SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.SHARD,
newShardName));
}
if (!ImplicitDocRouter.NAME.equals(((Map) clusterState.getCollection(req.getParams().get(COLLECTION_PROP)).get(DOC_ROUTER)).get(NAME)))
throw new SolrException(ErrorCode.BAD_REQUEST, "shards can be added only to 'implicit' collections");
@ -989,8 +986,8 @@ public class CollectionsHandler extends RequestHandlerBase {
private static void verifyShardsParam(String shardsParam) {
for (String shard : shardsParam.split(",")) {
if (!SolrIdentifierValidator.validateShardName(shard))
throw new SolrException(ErrorCode.BAD_REQUEST, "Invalid shard: " + shard
+ ". Shard names must consist entirely of periods, underscores, and alphanumerics");;
throw new SolrException(ErrorCode.BAD_REQUEST, SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.SHARD,
shard));
}
}

View File

@ -649,7 +649,7 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
final String errorMessage = e.getMessage();
assertTrue(errorMessage.contains("Invalid collection"));
assertTrue(errorMessage.contains("invalid@name#with$weird%characters"));
assertTrue(errorMessage.contains("Collection names must consist entirely of"));
assertTrue(errorMessage.contains("collection names must consist entirely of"));
}
}
}
@ -672,7 +672,7 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
final String errorMessage = e.getMessage();
assertTrue(errorMessage.contains("Invalid shard"));
assertTrue(errorMessage.contains("invalid@name#with$weird%characters"));
assertTrue(errorMessage.contains("Shard names must consist entirely of"));
assertTrue(errorMessage.contains("shard names must consist entirely of"));
}
}
}
@ -693,7 +693,7 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
final String errorMessage = e.getMessage();
assertTrue(errorMessage.contains("Invalid alias"));
assertTrue(errorMessage.contains("invalid@name#with$weird%characters"));
assertTrue(errorMessage.contains("Aliases must consist entirely of"));
assertTrue(errorMessage.contains("alias names must consist entirely of"));
}
}
}
@ -726,7 +726,7 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
final String errorMessage = e.getMessage();
assertTrue(errorMessage.contains("Invalid shard"));
assertTrue(errorMessage.contains("invalid@name#with$weird%characters"));
assertTrue(errorMessage.contains("Shard names must consist entirely of"));
assertTrue(errorMessage.contains("shard names must consist entirely of"));
}
}
}

View File

@ -292,15 +292,15 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
/**
* Provide the name of the shards to be created, separated by commas
*
* Shard names must consist entirely of periods, underscores, and alphanumerics. Other characters are not allowed.
* Shard names must consist entirely of periods, underscores, hyphens, and alphanumerics. Other characters are not allowed.
*
* @throws IllegalArgumentException if any of the shard names contain invalid characters.
*/
public Create setShards(String shards) {
for (String shard : shards.split(",")) {
if (!SolrIdentifierValidator.validateShardName(shard)) {
throw new IllegalArgumentException("Invalid shard: " + shard
+ ". Shard names must consist entirely of periods, underscores, and alphanumerics");
throw new IllegalArgumentException(SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.SHARD,
shard));
}
}
this.shards = shards;
@ -317,8 +317,8 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
@Override
public Create setCollectionName(String collectionName) throws SolrException {
if (!SolrIdentifierValidator.validateCollectionName(collectionName)) {
throw new IllegalArgumentException("Invalid collection: " + collectionName
+ ". Collection names must consist entirely of periods, underscores, and alphanumerics");
throw new IllegalArgumentException(SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.COLLECTION,
collectionName));
}
this.collection = collectionName;
return this;
@ -440,15 +440,15 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
/**
* Provide the name of the shard to be created.
*
* Shard names must consist entirely of periods, underscores, and alphanumerics. Other characters are not allowed.
* Shard names must consist entirely of periods, underscores, hyphens, and alphanumerics. Other characters are not allowed.
*
* @throws IllegalArgumentException if the shard name contains invalid characters.
*/
@Override
public CreateShard setShardName(String shardName) {
if (!SolrIdentifierValidator.validateShardName(shardName)) {
throw new IllegalArgumentException("Invalid shard: " + shardName
+ ". Shard names must consist entirely of periods, underscores, and alphanumerics");
throw new IllegalArgumentException(SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.SHARD,
shardName));
}
this.shardName = shardName;
return this;
@ -641,8 +641,8 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
*/
public CreateAlias setAliasName(String aliasName) {
if (!SolrIdentifierValidator.validateCollectionName(aliasName)) {
throw new IllegalArgumentException("Invalid alias: " + aliasName
+ ". Aliases must consist entirely of periods, underscores, and alphanumerics");
throw new IllegalArgumentException(SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.ALIAS,
aliasName));
}
this.aliasName = aliasName;
return this;

View File

@ -111,8 +111,8 @@ public class CoreAdminRequest extends SolrRequest<CoreAdminResponse> {
@Override
public void setCoreName(String coreName) {
if (!SolrIdentifierValidator.validateCoreName(coreName)) {
throw new IllegalArgumentException("Invalid core: " + coreName
+ ". Core names must consist entirely of periods, underscores, and alphanumerics");
throw new IllegalArgumentException(SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.CORE,
coreName));
}
this.core = coreName;
}
@ -560,8 +560,8 @@ public class CoreAdminRequest extends SolrRequest<CoreAdminResponse> {
public static CoreAdminResponse renameCore(String coreName, String newName, SolrClient client )
throws SolrServerException, IOException {
if (!SolrIdentifierValidator.validateCoreName(newName)) {
throw new IllegalArgumentException("Invalid core: " + newName
+ ". Core names must consist entirely of periods, underscores, and alphanumerics");
throw new IllegalArgumentException(SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.CORE,
newName));
}
CoreAdminRequest req = new CoreAdminRequest();

View File

@ -23,11 +23,15 @@ import java.util.regex.Pattern;
* Ensures that provided identifiers align with Solr's recommendations/requirements for choosing
* collection, core, etc identifiers.
*
* Identifiers are allowed to contain underscores, periods, and alphanumeric characters.
* Identifiers are allowed to contain underscores, periods, hyphens, and alphanumeric characters.
*/
public class SolrIdentifierValidator {
final static Pattern identifierPattern = Pattern.compile("^[\\._A-Za-z0-9]*$");
final static Pattern identifierPattern = Pattern.compile("^(?!\\-)[\\._A-Za-z0-9\\-]*$");
public enum IdentifierType {
SHARD, COLLECTION, CORE, ALIAS
}
public static boolean validateShardName(String shardName) {
return validateIdentifier(shardName);
}
@ -46,6 +50,12 @@ public class SolrIdentifierValidator {
}
return true;
}
public static String getIdentifierMessage(IdentifierType identifierType, String name) {
return "Invalid " + identifierType.toString().toLowerCase() + ": " + name + ". " + identifierType.toString().toLowerCase()
+ " names must consist entirely of periods, underscores, hyphens, and alphanumerics";
}
}

View File

@ -37,7 +37,7 @@ public class TestCollectionAdminRequest extends LuceneTestCase {
final String exceptionMessage = e.getMessage();
assertTrue(exceptionMessage.contains("Invalid collection"));
assertTrue(exceptionMessage.contains("invalid$collection@name"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, and alphanumerics"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, hyphens, and alphanumerics"));
}
}
@ -51,7 +51,7 @@ public class TestCollectionAdminRequest extends LuceneTestCase {
final String exceptionMessage = e.getMessage();
assertTrue(exceptionMessage.contains("Invalid shard"));
assertTrue(exceptionMessage.contains("invalid$shard@name"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, and alphanumerics"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, hyphens, and alphanumerics"));
}
}
@ -65,7 +65,7 @@ public class TestCollectionAdminRequest extends LuceneTestCase {
final String exceptionMessage = e.getMessage();
assertTrue(exceptionMessage.contains("Invalid alias"));
assertTrue(exceptionMessage.contains("invalid$alias@name"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, and alphanumerics"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, hyphens, and alphanumerics"));
}
}
@ -79,7 +79,7 @@ public class TestCollectionAdminRequest extends LuceneTestCase {
final String exceptionMessage = e.getMessage();
assertTrue(exceptionMessage.contains("Invalid shard"));
assertTrue(exceptionMessage.contains("invalid$shard@name"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, and alphanumerics"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, hyphens, and alphanumerics"));
}
}
}

View File

@ -171,7 +171,7 @@ public class TestCoreAdmin extends AbstractEmbeddedSolrServerTestCase {
final String exceptionMessage = e.getMessage();
assertTrue(exceptionMessage.contains("Invalid core"));
assertTrue(exceptionMessage.contains("invalid$core@name"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, and alphanumerics"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, hyphens, and alphanumerics"));
}
}
@ -184,7 +184,7 @@ public class TestCoreAdmin extends AbstractEmbeddedSolrServerTestCase {
final String exceptionMessage = e.getMessage();
assertTrue(e.getMessage(), exceptionMessage.contains("Invalid core"));
assertTrue(exceptionMessage.contains("invalid$core@name"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, and alphanumerics"));
assertTrue(exceptionMessage.contains("must consist entirely of periods, underscores, hyphens, and alphanumerics"));
}
}