SOLR-12938 - Cluster status now returns results for aliases instead of

throwing an exception
This commit is contained in:
Gus Heck 2018-11-04 12:01:51 -05:00
parent eb359ca079
commit 45b772f4a9
5 changed files with 74 additions and 13 deletions

View File

@ -90,6 +90,8 @@ New Features
* SOLR-12862: Add log10 Stream Evaluator and allow the pow Stream Evaluator to accept a vector of exponents (Joel Bernstein)
* SOLR-12938: Cluster Status returns results for aliases, instead of throwing exceptions (Gus Heck)
Other Changes
----------------------

View File

@ -26,6 +26,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.Aliases;
@ -92,6 +93,17 @@ public class ClusterStatus {
collectionsMap = Collections.singletonMap(collection, clusterState.getCollectionOrNull(collection));
}
boolean isAlias = aliasVsCollections.containsKey(collection);
boolean didNotFindCollection = collectionsMap.get(collection) == null;
if (didNotFindCollection && isAlias) {
// In this case this.collection is an alias name not a collection
// get all collections and filter out collections not in the alias
collectionsMap = clusterState.getCollectionsMap().entrySet().stream()
.filter((entry) -> aliasVsCollections.get(collection).contains(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
NamedList<Object> collectionProps = new SimpleOrderedMap<>();
for (Map.Entry<String, DocCollection> entry : collectionsMap.entrySet()) {

View File

@ -418,13 +418,17 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
private void clusterStatusAliasTest() throws Exception {
try (CloudSolrClient client = createCloudClient(null)) {
// create an alias named myalias
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("action", CollectionParams.CollectionAction.CREATEALIAS.toString());
params.set("name", "myalias");
params.set("collections", DEFAULT_COLLECTION + "," + COLLECTION_NAME);
SolrRequest request = new QueryRequest(params);
request.setPath("/admin/collections");
client.request(request);
// request a collection that's part of an alias
params = new ModifiableSolrParams();
params.set("action", CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
params.set("collection", DEFAULT_COLLECTION);
@ -433,7 +437,6 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
NamedList<Object> rsp = client.request(request);
NamedList<Object> cluster = (NamedList<Object>) rsp.get("cluster");
assertNotNull("Cluster state should not be null", cluster);
Map<String, String> aliases = (Map<String, String>) cluster.get("aliases");
@ -448,6 +451,38 @@ public class TestCollectionAPI extends ReplicaPropertiesBase {
assertEquals("conf1", collection.get("configName"));
List<String> collAlias = (List<String>) collection.get("aliases");
assertEquals("Aliases not found", Lists.newArrayList("myalias"), collAlias);
// status request on the alias itself
params = new ModifiableSolrParams();
params.set("action", CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
params.set("collection", "myalias");
request = new QueryRequest(params);
request.setPath("/admin/collections");
// SOLR-12938 - this should NOT cause an exception
rsp = client.request(request);
cluster = (NamedList<Object>) rsp.get("cluster");
assertNotNull("Cluster state should not be null", cluster);
collections = (NamedList<Object>) cluster.get("collections");
assertNotNull("Collections should not be null in cluster state", collections);
assertNotNull(collections.get(DEFAULT_COLLECTION));
assertNotNull(collections.get(COLLECTION_NAME));
// status request on something neither an alias nor a collection itself
params = new ModifiableSolrParams();
params.set("action", CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
params.set("collection", "notAnAliasOrCollection");
request = new QueryRequest(params);
request.setPath("/admin/collections");
// SOLR-12938 - this should still cause an exception
try {
client.request(request);
fail("requesting status for 'notAnAliasOrCollection' should cause an exception from CLUSTERSTATUS" );
} catch (RuntimeException e) {
// success
}
}
}

View File

@ -1663,7 +1663,7 @@ Fetch the cluster status including collections, shards, replicas, configuration
=== CLUSTERSTATUS Parameters
`collection`::
The collection name for which information is requested. If omitted, information on all collections in the cluster will be returned.
The collection or alias name for which information is requested. If omitted, information on all collections in the cluster will be returned. If an alias is supplied, information on the collections in the alias will be returned.
`shard`::
The shard(s) for which information is requested. Multiple shard names can be specified as a comma-separated list.

View File

@ -96,14 +96,13 @@ public class HttpClusterStateProvider implements ClusterStateProvider {
ClusterState cs = fetchClusterState(client, collection, null);
return cs.getCollectionRef(collection);
} catch (SolrServerException | RemoteSolrException | IOException e) {
if (e.getMessage().contains(collection + " not found")) {
// Cluster state for the given collection was not found.
// Lets fetch/update our aliases:
getAliases(true);
return null;
}
log.warn("Attempt to fetch cluster state from " +
Utils.getBaseUrlForNodeName(nodeName, urlScheme) + " failed.", e);
} catch (NotACollectionException e) {
// Cluster state for the given collection was not found, could be an alias.
// Lets fetch/update our aliases:
getAliases(true);
return null;
}
}
throw new RuntimeException("Tried fetching cluster state using the node names we knew of, i.e. " + liveNodes +". However, "
@ -114,7 +113,7 @@ public class HttpClusterStateProvider implements ClusterStateProvider {
}
@SuppressWarnings({"rawtypes", "unchecked"})
private ClusterState fetchClusterState(SolrClient client, String collection, Map<String, Object> clusterProperties) throws SolrServerException, IOException {
private ClusterState fetchClusterState(SolrClient client, String collection, Map<String, Object> clusterProperties) throws SolrServerException, IOException, NotACollectionException {
ModifiableSolrParams params = new ModifiableSolrParams();
if (collection != null) {
params.set("collection", collection);
@ -131,8 +130,12 @@ public class HttpClusterStateProvider implements ClusterStateProvider {
collectionsMap = ((NamedList)cluster.get("collections")).asMap(10);
}
int znodeVersion;
if (collection != null) {
znodeVersion = (int)((Map<String, Object>)(collectionsMap).get(collection)).get("znodeVersion");
Map<String, Object> collFromStatus = (Map<String, Object>) (collectionsMap).get(collection);
if (collection != null && collFromStatus == null) {
throw new NotACollectionException(); // probably an alias
}
if (collection != null) { // can be null if alias
znodeVersion = (int) collFromStatus.get("znodeVersion");
} else {
znodeVersion = -1;
}
@ -253,6 +256,10 @@ public class HttpClusterStateProvider implements ClusterStateProvider {
} catch (SolrServerException | RemoteSolrException | IOException e) {
log.warn("Attempt to fetch cluster state from " +
Utils.getBaseUrlForNodeName(nodeName, urlScheme) + " failed.", e);
} catch (NotACollectionException e) {
// Cluster state for the given collection was not found, could be an alias.
// Lets fetch/update our aliases:
getAliases(true);
}
}
throw new RuntimeException("Tried fetching cluster state using the node names we knew of, i.e. " + liveNodes +". However, "
@ -264,7 +271,7 @@ public class HttpClusterStateProvider implements ClusterStateProvider {
@Override
public Map<String, Object> getClusterProperties() {
for (String nodeName: liveNodes) {
for (String nodeName : liveNodes) {
try (HttpSolrClient client = new HttpSolrClient.Builder().
withBaseSolrUrl(Utils.getBaseUrlForNodeName(nodeName, urlScheme)).
withHttpClient(httpClient).build()) {
@ -274,9 +281,11 @@ public class HttpClusterStateProvider implements ClusterStateProvider {
} catch (SolrServerException | RemoteSolrException | IOException e) {
log.warn("Attempt to fetch cluster state from " +
Utils.getBaseUrlForNodeName(nodeName, urlScheme) + " failed.", e);
} catch (NotACollectionException e) {
// should be an an alias, don't care
}
}
throw new RuntimeException("Tried fetching cluster state using the node names we knew of, i.e. " + liveNodes +". However, "
throw new RuntimeException("Tried fetching cluster state using the node names we knew of, i.e. " + liveNodes + ". However, "
+ "succeeded in obtaining the cluster state from none of them."
+ "If you think your Solr cluster is up and is accessible,"
+ " you could try re-creating a new CloudSolrClient using working"
@ -309,4 +318,7 @@ public class HttpClusterStateProvider implements ClusterStateProvider {
this.cacheTimeout = cacheTimeout;
}
// This exception is not meant to escape this class it should be caught and wrapped.
private class NotACollectionException extends Exception {
}
}