This is an automated email from the ASF dual-hosted git repository.

ishan pushed a commit to branch jira/SOLR15694
in repository https://gitbox.apache.org/repos/asf/solr.git

commit a14085aaa705ab058cd25212dff19f9881f17002
Author: Ishan Chattopadhyaya <[email protected]>
AuthorDate: Sat Dec 18 15:12:13 2021 +0530

    Adding Roles API to ref guide
---
 .../java/org/apache/solr/handler/ClusterAPI.java   | 42 ++++++++--
 .../test/org/apache/solr/cloud/NodeRolesTest.java  | 18 ++--
 solr/solr-ref-guide/src/node-roles.adoc            | 97 +++++++++++++++++++++-
 3 files changed, 140 insertions(+), 17 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java 
b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
index 9f93c39..39f4750 100644
--- a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
@@ -103,10 +103,8 @@ public class ClusterAPI {
       }
       for (String child : children) {
         Object c = readRecursive(path + "/" + child, zk, depth - 1);
-
         result.put(child, c);
       }
-
     } catch (Exception e) {
       throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
     }
@@ -115,7 +113,6 @@ public class ClusterAPI {
     } else {
       return result;
     }
-
   }
 
   @EndPoint(method = GET,
@@ -123,16 +120,45 @@ public class ClusterAPI {
           permission = COLL_READ_PERM)
   public void nodesWithRole(SolrQueryRequest req, SolrQueryResponse rsp) 
throws Exception {
     String role = req.getPathTemplateValues().get("role");
-    rsp.add(role,
+    rsp.add("node-roles", Map.of(role,
             readRecursive(ZkStateReader.NODE_ROLES + "/"+ role,
-                    
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(),
 2));
+                    
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(),
 2)));
+  }
+
+  @EndPoint(method = GET,
+          path = "/cluster/node-roles/nodes/{node}",
+          permission = COLL_READ_PERM)
+  @SuppressWarnings("unchecked")
+  public void rolesForNode(SolrQueryRequest req, SolrQueryResponse rsp) throws 
Exception {
+    String node = req.getPathTemplateValues().get("node");
+    Map<String, String> ret = new HashMap<String, String>();
+    Map<String, Map<String, Set<String>>> roles = (Map<String, Map<String, 
Set<String>>>) readRecursive(ZkStateReader.NODE_ROLES,
+            
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(),
 3);
+    for (String role: roles.keySet()) {
+      for (String mode : roles.get(role).keySet()) {
+        if (roles.get(role).get(mode) instanceof List && ((List) 
roles.get(role).get(mode)).size() == 0) {
+          continue;
+        }
+        Set<String> nodes = roles.get(role).get(mode);
+        if (nodes.contains(node)) ret.put(role, mode);
+      }
+    }
+    for (String role: ret.keySet()) {
+      rsp.add(role, ret.get(role));
+    }
   }
+
   @EndPoint(method = GET,
           path = "/cluster/node-roles/supported",
           permission = COLL_READ_PERM)
   public void supportedRoles(SolrQueryRequest req, SolrQueryResponse rsp) 
throws Exception {
-    rsp.add("supported-roles",
-                    
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager().listData(ZkStateReader.NODE_ROLES));
+    //rsp.add("supported-roles",
+    //                
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager().listData(ZkStateReader.NODE_ROLES));
+    Map<String, Object> roleModesSupportedMap = new HashMap<>();
+    for (NodeRoles.Role role: NodeRoles.Role.values()) {
+      roleModesSupportedMap.put(role.toString(), Map.of("modes", 
role.supportedModes(), "defaultIfAbsent", role.defaultIfAbsent()));
+    }
+    rsp.add("supported-roles", roleModesSupportedMap);
   }
 
   @EndPoint(method = GET,
@@ -143,7 +169,7 @@ public class ClusterAPI {
     String roleVal = req.getPathTemplateValues().get("role-val");
     List<String> nodes =  
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager()
             .getDistribStateManager().listData(ZkStateReader.NODE_ROLES + "/"+ 
role+"/"+roleVal);
-    rsp.add( role, Collections.singletonMap(roleVal, nodes));
+    rsp.add( "node-roles", Map.of(role, Collections.singletonMap(roleVal, 
nodes)));
   }
 
    public static List<String> getNodesByRole(NodeRoles.Role role, String val, 
DistribStateManager zk)
diff --git a/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java 
b/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java
index cda83ad..1970f6c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java
@@ -22,6 +22,8 @@ import java.util.Collection;
 import java.util.Collections;
 
 import java.util.List;
+import java.util.Map;
+
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.V2Request;
@@ -52,9 +54,9 @@ public class NodeRolesTest extends SolrCloudTestCase {
     JettySolrRunner j0 = cluster.getJettySolrRunner(0);
     JettySolrRunner j1 = null, j2 = null;
     V2Response rsp = new 
V2Request.Builder("/cluster/node-roles/supported").GET().build().process(cluster.getSolrClient());
-    List<String> l = (List<String>) rsp._get("supported-roles", 
Collections.emptyList());
-    assertTrue(l.contains("data"));
-    assertTrue(l.contains("overseer"));
+    Map<String, Object> l = (Map<String, Object>) rsp._get("supported-roles", 
Collections.emptyMap());
+    assertTrue(l.containsKey("data"));
+    assertTrue(l.containsKey("overseer"));
 
     j1 = startNodeWithRoles("overseer:preferred,data:off");
 
@@ -72,12 +74,12 @@ public class NodeRolesTest extends SolrCloudTestCase {
 
     rsp = new 
V2Request.Builder("/cluster/node-roles/overseer").GET().build().process(cluster.getSolrClient());
 
-    assertTrue( ((Collection)rsp._get("overseer/preferred", 
Collections.emptyList())).contains(j2.getNodeName()));
-    assertTrue( ((Collection)rsp._get("overseer/preferred", 
Collections.emptyList())).contains(j1.getNodeName()));
+    assertTrue( ((Collection)rsp._get("node-roles/overseer/preferred", 
Collections.emptyList())).contains(j2.getNodeName()));
+    assertTrue( ((Collection)rsp._get("node-roles/overseer/preferred", 
Collections.emptyList())).contains(j1.getNodeName()));
 
     rsp = new 
V2Request.Builder("/cluster/node-roles/overseer/preferred").GET().build().process(cluster.getSolrClient());
-    assertTrue( ((Collection)rsp._get("overseer/preferred", 
Collections.emptyList())).contains(j2.getNodeName()));
-    assertTrue( ((Collection)rsp._get("overseer/preferred", 
Collections.emptyList())).contains(j1.getNodeName()));
+    assertTrue( ((Collection)rsp._get("node-roles/overseer/preferred", 
Collections.emptyList())).contains(j2.getNodeName()));
+    assertTrue( ((Collection)rsp._get("node-roles/overseer/preferred", 
Collections.emptyList())).contains(j1.getNodeName()));
 
     String COLLECTION_NAME = "TEST_ROLES";
     CollectionAdminRequest
@@ -93,7 +95,7 @@ public class NodeRolesTest extends SolrCloudTestCase {
     // Shutdown the dedicated overseer, make sure that node disappears from 
the roles output
     j1.stop();
     rsp = new 
V2Request.Builder("/cluster/node-roles/overseer/preferred").GET().build().process(cluster.getSolrClient());
-    assertFalse (((Collection) rsp._get("overseer/preferred" , null)). 
contains(j1.getNodeName()));
+    assertFalse (((Collection) rsp._get("node-roles/overseer/preferred" , 
null)). contains(j1.getNodeName()));
   }
 
   private JettySolrRunner startNodeWithRoles(String roles) throws Exception {
diff --git a/solr/solr-ref-guide/src/node-roles.adoc 
b/solr/solr-ref-guide/src/node-roles.adoc
index f3e5969..ed2c07a 100644
--- a/solr/solr-ref-guide/src/node-roles.adoc
+++ b/solr/solr-ref-guide/src/node-roles.adoc
@@ -62,4 +62,99 @@ A common situation arises when the nodes in a cluster is 
under heavy querying or
 * Most nodes, say 10 of them, in the cluster start with 
`-Dsolr.node.roles=data:on,overseer:allowed` (or with no parameter, since the 
default value for `solr.node.roles` is the same).
 * One or more nodes can start with `-Dsolr.node.roles=overseer:preferred` (or 
`-Dsolr.node.roles=overseer:preferred,data:off`)
 
-In this arrangement, such dedicated nodes can have lesser resources than other 
data nodes (since these are stateless nodes) and yet the cluster will behave 
optimally. In case the dedicated overseer nodes go down for some reason, the 
overseer leader will be elected from one of the data nodes (since they have 
overseer in "allowed" mode), and once one of the dedicated overseer nodes are 
back up, it will assume the overseer leadership again.
\ No newline at end of file
+In this arrangement, such dedicated nodes can have lesser resources than other 
data nodes (since these are stateless nodes) and yet the cluster will behave 
optimally. In case the dedicated overseer nodes go down for some reason, the 
overseer leader will be elected from one of the data nodes (since they have 
overseer in "allowed" mode), and once one of the dedicated overseer nodes are 
back up, it will assume the overseer leadership again.
+
+== Roles API
+
+=== GET /api/cluster/node-roles/supported
+
+*Input*
+[source,text]
+----
+curl http://localhost:8983/api/cluster/node-roles/supported
+----
+
+*Output*
+[source,text]
+----
+{
+  "supported-roles":{
+    "data":{
+      "defaultIfAbsent":"off",
+      "modes":["off",
+        "on"]
+    },
+    "overseer":{
+      "defaultIfAbsent":"disallowed",
+      "modes":["disallowed",
+        "allowed",
+        "preferred"]
+    }
+  }
+}
+----
+
+=== GET /api/cluster/node-roles
+
+*Input*
+[source,text]
+----
+curl http://localhost:8983/api/cluster/node-roles
+----
+
+*Output*
+[source,text]
+----
+{
+  "node-roles":{
+    "data":{
+      "off":["solr2:8983_solr"],
+      "on":["solr1:8983_solr"]
+    },
+    "overseer":{
+      "allowed":["solr1:8983_solr"],
+      "disallowed":[],
+      "preferred":["solr2:8983_solr"]
+    }
+  }
+}
+----
+
+=== GET /api/cluster/node-roles/{role}
+
+*Input*
+[source,text]
+----
+http://localhost:8983/api/node-roles/data
+----
+
+*Output*
+[source,text]
+----
+{
+  "node-roles":{
+    "data":{
+      "off":["solr2:8983_solr"],
+      "on":["solr1:8983_solr"]
+    }
+  }
+}
+----
+
+
+=== GET /api/cluster/node-roles/nodes/{node}
+
+*Input*
+[source,text]
+----
+curl http://localhost:8983/api/cluster/node-roles/nodes/solr1:8983_solr
+----
+
+*Output*
+[source,text]
+----
+{
+  "data":"on",
+  "overseer":"allowed"
+}
+----

Reply via email to