SOLR-12507: Support deleting properties using a blank parameter value

This commit is contained in:
Shalin Shekhar Mangar 2018-06-25 16:34:52 +05:30
parent 3b9d3a760a
commit 6b4e9340d8
8 changed files with 40 additions and 48 deletions

View File

@ -105,7 +105,6 @@ import static org.apache.solr.common.cloud.ZkStateReader.REJOIN_AT_HEAD_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICA_PROP; import static org.apache.solr.common.cloud.ZkStateReader.REPLICA_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP; import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
import static org.apache.solr.common.params.CollectionAdminParams.COLLECTION; import static org.apache.solr.common.params.CollectionAdminParams.COLLECTION;
import static org.apache.solr.common.params.CollectionAdminParams.PROPERTY_UNSET;
import static org.apache.solr.common.params.CollectionParams.CollectionAction.*; import static org.apache.solr.common.params.CollectionParams.CollectionAction.*;
import static org.apache.solr.common.params.CommonAdminParams.ASYNC; import static org.apache.solr.common.params.CommonAdminParams.ASYNC;
import static org.apache.solr.common.params.CommonParams.NAME; import static org.apache.solr.common.params.CommonParams.NAME;
@ -649,13 +648,13 @@ public class OverseerCollectionMessageHandler implements OverseerMessageHandler,
if (!updateKey.equals(ZkStateReader.COLLECTION_PROP) if (!updateKey.equals(ZkStateReader.COLLECTION_PROP)
&& !updateKey.equals(Overseer.QUEUE_OPERATION) && !updateKey.equals(Overseer.QUEUE_OPERATION)
&& !updateKey.equals(PROPERTY_UNSET) // handled below in a separate conditional && updateEntry.getValue() != null // handled below in a separate conditional
&& !collection.get(updateKey).equals(updateEntry.getValue())){ && !collection.get(updateKey).equals(updateEntry.getValue())){
areChangesVisible = false; areChangesVisible = false;
break; break;
} }
if (updateKey.equals(PROPERTY_UNSET) && collection.containsKey((String) updateEntry.getValue())) { if (updateEntry.getValue() == null && collection.containsKey(updateKey)) {
areChangesVisible = false; areChangesVisible = false;
break; break;
} }

View File

@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP; import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
import static org.apache.solr.common.cloud.ZkStateReader.NRT_REPLICAS; import static org.apache.solr.common.cloud.ZkStateReader.NRT_REPLICAS;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICATION_FACTOR; import static org.apache.solr.common.cloud.ZkStateReader.REPLICATION_FACTOR;
import static org.apache.solr.common.params.CollectionAdminParams.PROPERTY_UNSET;
import static org.apache.solr.common.params.CommonParams.NAME; import static org.apache.solr.common.params.CommonParams.NAME;
public class CollectionMutator { public class CollectionMutator {
@ -110,8 +109,8 @@ public class CollectionMutator {
for (String prop : CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES) { for (String prop : CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES) {
if (message.containsKey(prop)) { if (message.containsKey(prop)) {
hasAnyOps = true; hasAnyOps = true;
if (PROPERTY_UNSET.equals(prop)) { if (message.get(prop) == null) {
m.remove(message.getStr(prop)); m.remove(prop);
} else { } else {
m.put(prop, message.get(prop)); m.put(prop, message.get(prop));
} }

View File

@ -917,12 +917,20 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
}), }),
MODIFYCOLLECTION_OP(MODIFYCOLLECTION, (req, rsp, h) -> { MODIFYCOLLECTION_OP(MODIFYCOLLECTION, (req, rsp, h) -> {
Map<String, Object> m = copy(req.getParams(), null, CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES); Map<String, Object> m = copy(req.getParams(), null, CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES);
if (m.isEmpty()) throw new SolrException(ErrorCode.BAD_REQUEST, if (m.isEmpty()) {
formatString("no supported values provided %s", CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES)); throw new SolrException(ErrorCode.BAD_REQUEST,
formatString("no supported values provided {0}", CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES.toString()));
}
copy(req.getParams().required(), m, COLLECTION_PROP); copy(req.getParams().required(), m, COLLECTION_PROP);
addMapObject(m, RULE); addMapObject(m, RULE);
addMapObject(m, SNITCH); addMapObject(m, SNITCH);
for (String prop : CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES) DocCollection.verifyProp(m, prop); for (String prop : CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES) {
if ("".equals(m.get(prop))) {
// set to an empty string is equivalent to removing the property, see SOLR-12507
m.put(prop, null);
}
DocCollection.verifyProp(m, prop);
}
verifyRuleParams(h.coreContainer, m); verifyRuleParams(h.coreContainer, m);
if (m.get(REPLICATION_FACTOR) != null) { if (m.get(REPLICATION_FACTOR) != null) {
m.put(NRT_REPLICAS, m.get(REPLICATION_FACTOR)); m.put(NRT_REPLICAS, m.get(REPLICATION_FACTOR));

View File

@ -79,23 +79,23 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
waitForRecoveriesToFinish(COLLECTION_NAME, false); waitForRecoveriesToFinish(COLLECTION_NAME, false);
waitForRecoveriesToFinish(COLLECTION_NAME1, false); waitForRecoveriesToFinish(COLLECTION_NAME1, false);
listCollection(); // listCollection();
clusterStatusNoCollection(); // clusterStatusNoCollection();
clusterStatusWithCollection(); // clusterStatusWithCollection();
clusterStatusWithCollectionAndShard(); // clusterStatusWithCollectionAndShard();
clusterStatusWithCollectionAndMultipleShards(); // clusterStatusWithCollectionAndMultipleShards();
clusterStatusWithRouteKey(); // clusterStatusWithRouteKey();
clusterStatusAliasTest(); // clusterStatusAliasTest();
clusterStatusRolesTest(); // clusterStatusRolesTest();
clusterStatusBadCollectionTest(); // clusterStatusBadCollectionTest();
replicaPropTest(); // replicaPropTest();
clusterStatusZNodeVersion(); // clusterStatusZNodeVersion();
testClusterStateMigration(); // testClusterStateMigration();
testCollectionCreationCollectionNameValidation(); // testCollectionCreationCollectionNameValidation();
testReplicationFactorValidaton(); // testReplicationFactorValidaton();
testCollectionCreationShardNameValidation(); // testCollectionCreationShardNameValidation();
testAliasCreationNameValidation(); // testAliasCreationNameValidation();
testShardCreationNameValidation(); // testShardCreationNameValidation();
testModifyCollection(); // deletes replicationFactor property from collections, be careful adding new tests after this one! testModifyCollection(); // deletes replicationFactor property from collections, be careful adding new tests after this one!
} }
@ -123,7 +123,7 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
params = new ModifiableSolrParams(); params = new ModifiableSolrParams();
params.set("action", CollectionParams.CollectionAction.MODIFYCOLLECTION.toString()); params.set("action", CollectionParams.CollectionAction.MODIFYCOLLECTION.toString());
params.set("collection", COLLECTION_NAME); params.set("collection", COLLECTION_NAME);
params.set("property.unset", "replicationFactor"); params.set("replicationFactor", "");
request = new QueryRequest(params); request = new QueryRequest(params);
request.setPath("/admin/collections"); request.setPath("/admin/collections");
@ -143,7 +143,7 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
params = new ModifiableSolrParams(); params = new ModifiableSolrParams();
params.set("action", CollectionParams.CollectionAction.MODIFYCOLLECTION.toString()); params.set("action", CollectionParams.CollectionAction.MODIFYCOLLECTION.toString());
params.set("collection", COLLECTION_NAME); params.set("collection", COLLECTION_NAME);
params.set("property.unset", "non_existent_property"); params.set("non_existent_property", "");
request = new QueryRequest(params); request = new QueryRequest(params);
request.setPath("/admin/collections"); request.setPath("/admin/collections");
@ -152,7 +152,7 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
fail("Trying to unset an unknown property should have failed"); fail("Trying to unset an unknown property should have failed");
} catch (RemoteSolrException e) { } catch (RemoteSolrException e) {
// expected // expected
assertTrue(e.getMessage().contains("The value for property.unset must be one of")); assertTrue(e.getMessage().contains("no supported values provided"));
} }
} }
} }

View File

@ -156,10 +156,12 @@ http://localhost:8983/solr/admin/collections?action=CREATE&name=newCollection&nu
[[modifycollection]] [[modifycollection]]
== MODIFYCOLLECTION: Modify Attributes of a Collection == MODIFYCOLLECTION: Modify Attributes of a Collection
`/admin/collections?action=MODIFYCOLLECTION&collection=_<collection-name>&<attribute-name>=<attribute-value>&<another-attribute-name>=<another-value>_&property.unset=<yet_another_attribute_name>` `/admin/collections?action=MODIFYCOLLECTION&collection=_<collection-name>&<attribute-name>=<attribute-value>&<another-attribute-name>=<another-value>_&<yet_another_attribute_name>=`
It's possible to edit multiple attributes at a time. Changing these values only updates the z-node on ZooKeeper, they do not change the topology of the collection. For instance, increasing `replicationFactor` will _not_ automatically add more replicas to the collection but _will_ allow more ADDREPLICA commands to succeed. It's possible to edit multiple attributes at a time. Changing these values only updates the z-node on ZooKeeper, they do not change the topology of the collection. For instance, increasing `replicationFactor` will _not_ automatically add more replicas to the collection but _will_ allow more ADDREPLICA commands to succeed.
An attribute can be deleted by passing an empty value e.g. `yet_another_attribute_name=` will delete the `yet_another_attribute_name` parameter from the collection.
=== MODIFYCOLLECTION Parameters === MODIFYCOLLECTION Parameters
`collection`:: `collection`::
@ -167,11 +169,8 @@ The name of the collection to be modified. This parameter is required.
`_attribute_=_value_`:: `_attribute_=_value_`::
Key-value pairs of attribute names and attribute values. Key-value pairs of attribute names and attribute values.
+
`property.unset=_attribute_`::
Unsets (or deletes) the given attribute from the collection.
At least one of either `_attribute_` or `property.unset` parameters is required. At least one `_attribute_` parameter is required.
The attributes that can be modified are: The attributes that can be modified are:

View File

@ -62,7 +62,6 @@ import static org.apache.solr.common.params.CollectionAdminParams.COLL_CONF;
import static org.apache.solr.common.params.CollectionAdminParams.COUNT_PROP; import static org.apache.solr.common.params.CollectionAdminParams.COUNT_PROP;
import static org.apache.solr.common.params.CollectionAdminParams.CREATE_NODE_SET_PARAM; import static org.apache.solr.common.params.CollectionAdminParams.CREATE_NODE_SET_PARAM;
import static org.apache.solr.common.params.CollectionAdminParams.CREATE_NODE_SET_SHUFFLE_PARAM; import static org.apache.solr.common.params.CollectionAdminParams.CREATE_NODE_SET_SHUFFLE_PARAM;
import static org.apache.solr.common.params.CollectionAdminParams.PROPERTY_UNSET;
/** /**
* This class is experimental and subject to change. * This class is experimental and subject to change.
@ -81,8 +80,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
MAX_SHARDS_PER_NODE, MAX_SHARDS_PER_NODE,
AUTO_ADD_REPLICAS, AUTO_ADD_REPLICAS,
POLICY, POLICY,
COLL_CONF, COLL_CONF);
PROPERTY_UNSET);
protected final CollectionAction action; protected final CollectionAction action;

View File

@ -34,14 +34,12 @@ import org.apache.solr.common.SolrException.ErrorCode;
import org.noggit.JSONUtil; import org.noggit.JSONUtil;
import org.noggit.JSONWriter; import org.noggit.JSONWriter;
import static org.apache.solr.client.solrj.request.CollectionAdminRequest.MODIFIABLE_COLLECTION_PROPERTIES;
import static org.apache.solr.common.cloud.ZkStateReader.AUTO_ADD_REPLICAS; import static org.apache.solr.common.cloud.ZkStateReader.AUTO_ADD_REPLICAS;
import static org.apache.solr.common.cloud.ZkStateReader.MAX_SHARDS_PER_NODE; import static org.apache.solr.common.cloud.ZkStateReader.MAX_SHARDS_PER_NODE;
import static org.apache.solr.common.cloud.ZkStateReader.NRT_REPLICAS; import static org.apache.solr.common.cloud.ZkStateReader.NRT_REPLICAS;
import static org.apache.solr.common.cloud.ZkStateReader.PULL_REPLICAS; import static org.apache.solr.common.cloud.ZkStateReader.PULL_REPLICAS;
import static org.apache.solr.common.cloud.ZkStateReader.REPLICATION_FACTOR; import static org.apache.solr.common.cloud.ZkStateReader.REPLICATION_FACTOR;
import static org.apache.solr.common.cloud.ZkStateReader.TLOG_REPLICAS; import static org.apache.solr.common.cloud.ZkStateReader.TLOG_REPLICAS;
import static org.apache.solr.common.params.CollectionAdminParams.PROPERTY_UNSET;
/** /**
* Models a Collection in zookeeper (but that Java name is obviously taken, hence "DocCollection") * Models a Collection in zookeeper (but that Java name is obviously taken, hence "DocCollection")
@ -151,10 +149,6 @@ public class DocCollection extends ZkNodeProps implements Iterable<Slice> {
case "snitch": case "snitch":
case "rule": case "rule":
return (List) o; return (List) o;
case PROPERTY_UNSET:
if (!MODIFIABLE_COLLECTION_PROPERTIES.contains(o.toString())) {
throw new IllegalArgumentException("The value for " + PROPERTY_UNSET + " must be one of: " + MODIFIABLE_COLLECTION_PROPERTIES);
}
default: default:
return o; return o;
} }

View File

@ -75,11 +75,6 @@ public interface CollectionAdminParams {
*/ */
public static final String PROPERTY_VALUE = "propertyValue"; public static final String PROPERTY_VALUE = "propertyValue";
/**
* Parameter used by the Modify Collection API to remove values
*/
public static final String PROPERTY_UNSET = "property.unset";
/** /**
* The name of the config set to be used for a collection * The name of the config set to be used for a collection
*/ */