-
Notifications
You must be signed in to change notification settings - Fork 814
Migrate org.apache.solr.cli tools from V1 to V2 APIs #4154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 8 commits
3a1d553
ee032f9
5b9c8f7
93c1717
4f5f0d4
93ed8ca
c8fdd3f
13c4bcc
eb58b9a
76e05ee
9cb9625
c57988e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| * contributor license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright ownership. | ||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with | ||
| * the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.apache.solr.client.api.endpoint; | ||
|
|
||
| import io.swagger.v3.oas.annotations.Operation; | ||
| import jakarta.ws.rs.GET; | ||
| import jakarta.ws.rs.Path; | ||
| import org.apache.solr.client.api.model.ListClusterNodesResponse; | ||
|
|
||
| /** V2 API definition for listing the live nodes in the SolrCloud cluster. */ | ||
| @Path("/cluster/nodes") | ||
| public interface ListClusterNodesApi { | ||
|
|
||
| @GET | ||
| @Operation( | ||
| summary = "List the live nodes in this Solr cluster.", | ||
| tags = {"cluster"}) | ||
| ListClusterNodesResponse listClusterNodes(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| * contributor license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright ownership. | ||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with | ||
| * the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.apache.solr.client.api.model; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import java.util.Set; | ||
|
|
||
| /** Response for the v2 "list cluster nodes" API */ | ||
| public class ListClusterNodesResponse extends SolrJerseyResponse { | ||
|
|
||
| @Schema(description = "The live nodes in the cluster.") | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also want to confirm that this api is for "live nodes" and not "all nodes" including dead ones?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and it is.. |
||
| @JsonProperty("nodes") | ||
| public Set<String> nodes; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,7 +27,6 @@ | |
| import java.nio.file.Path; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Locale; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
|
|
@@ -41,15 +40,14 @@ | |
| import org.apache.solr.client.solrj.impl.CloudSolrClient; | ||
| import org.apache.solr.client.solrj.impl.SolrZkClientTimeout; | ||
| import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; | ||
| import org.apache.solr.client.solrj.request.CollectionAdminRequest; | ||
| import org.apache.solr.client.solrj.request.CollectionsApi; | ||
| import org.apache.solr.client.solrj.request.CoresApi; | ||
| import org.apache.solr.client.solrj.request.SystemInfoRequest; | ||
| import org.apache.solr.client.solrj.response.SystemInfoResponse; | ||
| import org.apache.solr.common.SolrException; | ||
| import org.apache.solr.common.cloud.SolrZkClient; | ||
| import org.apache.solr.common.cloud.ZkStateReader; | ||
| import org.apache.solr.common.util.EnvUtils; | ||
| import org.apache.solr.common.util.NamedList; | ||
|
|
||
| /** Utility class that holds various helper methods for the CLI. */ | ||
| public final class CLIUtils { | ||
|
|
@@ -311,10 +309,11 @@ public static boolean safeCheckCollectionExists( | |
| String solrUrl, String collection, String credentials) { | ||
| boolean exists = false; | ||
| try (var solrClient = getSolrClient(solrUrl, credentials)) { | ||
| NamedList<Object> existsCheckResult = solrClient.request(new CollectionAdminRequest.List()); | ||
| @SuppressWarnings("unchecked") | ||
| List<String> collections = (List<String>) existsCheckResult.get("collections"); | ||
| exists = collections != null && collections.contains(collection); | ||
| var response = new CollectionsApi.ListCollections().process(solrClient); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [0] I may be out of date, but as of one point at least these generated v2 request/response objects didn't throw exception on errors the way everything else in SolrJ does. Assuming this is still true, users are responsible for inspecting the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, I just merged in the main branch with the new fix... I don't really want to litter our tests with a whole bunch of tests on "do we handle it when the api throws an exception"... wiht your other work, can we call this as good? |
||
| exists = | ||
| response != null | ||
| && response.collections != null | ||
| && response.collections.contains(collection); | ||
| } catch (Exception exc) { | ||
| // just ignore it since we're only interested in a positive result here | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,10 +31,10 @@ | |
| import org.apache.commons.cli.Options; | ||
| import org.apache.solr.cli.SolrProcessManager.SolrProcess; | ||
| import org.apache.solr.client.solrj.SolrClient; | ||
| import org.apache.solr.client.solrj.request.CollectionAdminRequest; | ||
| import org.apache.solr.client.solrj.request.ClusterApi; | ||
| import org.apache.solr.client.solrj.request.CollectionsApi; | ||
| import org.apache.solr.client.solrj.request.SystemInfoRequest; | ||
| import org.apache.solr.client.solrj.response.SystemInfoResponse; | ||
| import org.apache.solr.common.util.NamedList; | ||
| import org.apache.solr.common.util.URLUtil; | ||
| import org.noggit.CharArr; | ||
| import org.noggit.JSONWriter; | ||
|
|
@@ -318,23 +318,24 @@ public static Map<String, Object> reportStatus(SolrClient solrClient) throws Exc | |
| } | ||
|
|
||
| /** | ||
| * Calls the CLUSTERSTATUS endpoint in Solr to get basic status information about the SolrCloud | ||
| * cluster. | ||
| * Calls V2 API endpoints to get basic status information about the SolrCloud cluster. | ||
| * | ||
| * <p>Uses GET /cluster/nodes for live node count and GET /collections for collection count. | ||
| */ | ||
| @SuppressWarnings("unchecked") | ||
| private static Map<String, String> getCloudStatus(SolrClient solrClient, String zkHost) | ||
| throws Exception { | ||
| Map<String, String> cloudStatus = new LinkedHashMap<>(); | ||
| cloudStatus.put("ZooKeeper", (zkHost != null) ? zkHost : "?"); | ||
|
|
||
| // TODO add booleans to request just what we want; not everything | ||
| NamedList<Object> json = solrClient.request(new CollectionAdminRequest.ClusterStatus()); | ||
|
|
||
| List<String> liveNodes = (List<String>) json._get(List.of("cluster", "live_nodes"), null); | ||
| cloudStatus.put("liveNodes", String.valueOf(liveNodes.size())); | ||
| var nodesResponse = new ClusterApi.ListClusterNodes().process(solrClient); | ||
| var liveNodes = nodesResponse != null ? nodesResponse.nodes : null; | ||
| cloudStatus.put("liveNodes", String.valueOf(liveNodes != null ? liveNodes.size() : 0)); | ||
|
|
||
| // TODO get this as a metric from the metrics API instead, or something else. | ||
| var collections = (Map<String, Object>) json._get(List.of("cluster", "collections"), null); | ||
| var collectionsResponse = new CollectionsApi.ListCollections().process(solrClient); | ||
gerlowskija marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| var collections = | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love all these |
||
| collectionsResponse != null && collectionsResponse.collections != null | ||
| ? collectionsResponse.collections | ||
| : List.of(); | ||
| cloudStatus.put("collections", String.valueOf(collections.size())); | ||
|
|
||
| return cloudStatus; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still very fuzzy on how all this magic works! @gerlowskija I would really appreciate your reivewing the new endpoint. One thing I want to confirm is that we already HAVE a v2 /cluster/nodes. However, it was not (I believe) using the annotaitons os it meant the V2 wasn't in solrJ due to no openapi specs. Hence I had a GenericSolrRequest until I created this. (I being copilot).