Skip to content

Commit d330fde

Browse files
committed
Enable picocli for some tools
1 parent d407fbf commit d330fde

File tree

8 files changed

+340
-72
lines changed

8 files changed

+340
-72
lines changed

solr/core/src/java/org/apache/solr/cli/HealthcheckTool.java

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,35 @@
5151
import org.slf4j.LoggerFactory;
5252

5353
/** Supports healthcheck command in the bin/solr script. */
54+
@picocli.CommandLine.Command(
55+
name = "healthcheck",
56+
description = "Check the health of a SolrCloud collection.")
5457
public class HealthcheckTool extends ToolBase {
5558
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
5659

60+
@picocli.CommandLine.Option(
61+
names = {"-c", "--name"},
62+
required = true,
63+
description = "Name of the collection to check.")
64+
private String collection;
65+
66+
// NOCOMMIT: Find a way to make this common for all tools that need it
67+
@picocli.CommandLine.Option(
68+
names = {"-z", "--zk-host"},
69+
description =
70+
"Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to "
71+
+ CommonCLIOptions.DefaultValues.ZK_HOST
72+
+ '.',
73+
required = true)
74+
String zkHost;
75+
76+
@picocli.CommandLine.Option(
77+
names = {"-u", "--credentials"},
78+
description =
79+
"Credentials in the format username:password. Example: --credentials solr:SolrRocks")
80+
private String credentials;
81+
82+
@Deprecated
5783
private static final Option COLLECTION_NAME_OPTION =
5884
Option.builder("c")
5985
.longOpt("name")
@@ -89,15 +115,17 @@ public HealthcheckTool(PrintStream stdout) {
89115

90116
@Override
91117
public void runImpl(CommandLine cli) throws Exception {
92-
String zkHost = CLIUtils.getZkHost(cli);
118+
zkHost = CLIUtils.getZkHost(cli);
119+
collection = cli.getOptionValue(COLLECTION_NAME_OPTION);
120+
93121
if (zkHost == null) {
94122
CLIO.err("Healthcheck tool only works in Solr Cloud mode.");
95123
System.exit(1);
96124
}
97125
try (CloudHttp2SolrClient cloudSolrClient = CLIUtils.getCloudHttp2SolrClient(zkHost)) {
98126
echoIfVerbose("\nConnecting to ZooKeeper at " + zkHost + " ...");
99127
cloudSolrClient.connect();
100-
runCloudTool(cloudSolrClient, cli);
128+
runCloudTool(cloudSolrClient);
101129
}
102130
}
103131

@@ -106,8 +134,7 @@ public String getName() {
106134
return "healthcheck";
107135
}
108136

109-
protected void runCloudTool(CloudSolrClient cloudSolrClient, CommandLine cli) throws Exception {
110-
String collection = cli.getOptionValue(COLLECTION_NAME_OPTION);
137+
protected void runCloudTool(CloudSolrClient cloudSolrClient) throws Exception {
111138

112139
log.debug("Running healthcheck for {}", collection);
113140

@@ -168,15 +195,11 @@ protected void runCloudTool(CloudSolrClient cloudSolrClient, CommandLine cli) th
168195
q = new SolrQuery("*:*");
169196
q.setRows(0);
170197
q.set(DISTRIB, "false");
171-
try (var solrClientForCollection =
172-
CLIUtils.getSolrClient(
173-
coreUrl, cli.getOptionValue(CommonCLIOptions.CREDENTIALS_OPTION))) {
198+
try (var solrClientForCollection = CLIUtils.getSolrClient(coreUrl, credentials)) {
174199
qr = solrClientForCollection.query(q);
175200
numDocs = qr.getResults().getNumFound();
176201
try (var solrClient =
177-
CLIUtils.getSolrClient(
178-
replicaCoreProps.getBaseUrl(),
179-
cli.getOptionValue(CommonCLIOptions.CREDENTIALS_OPTION))) {
202+
CLIUtils.getSolrClient(replicaCoreProps.getBaseUrl(), credentials)) {
180203
NamedList<Object> systemInfo =
181204
solrClient.request(
182205
new GenericSolrRequest(
@@ -227,6 +250,20 @@ protected void runCloudTool(CloudSolrClient cloudSolrClient, CommandLine cli) th
227250
new JSONWriter(arr, 2).write(report);
228251
echo(arr.toString());
229252
}
253+
254+
@Override
255+
public int callTool() throws Exception {
256+
if (zkHost == null) {
257+
CLIO.err("Healthcheck tool only works in Solr Cloud mode.");
258+
return 1;
259+
}
260+
try (CloudHttp2SolrClient cloudSolrClient = CLIUtils.getCloudHttp2SolrClient(zkHost)) {
261+
echoIfVerbose("\nConnecting to ZooKeeper at " + zkHost + " ...");
262+
cloudSolrClient.connect();
263+
runCloudTool(cloudSolrClient);
264+
}
265+
return 0;
266+
}
230267
}
231268

232269
class ReplicaHealth implements Comparable<ReplicaHealth> {

solr/core/src/java/org/apache/solr/cli/SolrCLI.java

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,50 @@
3838
import org.apache.commons.cli.Option;
3939
import org.apache.commons.cli.Options;
4040
import org.apache.commons.cli.ParseException;
41+
import org.apache.solr.client.api.util.SolrVersion;
4142
import org.apache.solr.client.solrj.SolrClient;
4243
import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
4344
import org.apache.solr.common.util.ContentStreamBase;
45+
import org.apache.solr.common.util.EnvUtils;
4446
import org.apache.solr.common.util.NamedList;
4547
import org.apache.solr.util.configuration.SSLConfigurationsFactory;
4648
import org.slf4j.Logger;
4749
import org.slf4j.LoggerFactory;
4850

4951
/** Command-line utility for working with Solr. */
52+
@picocli.CommandLine.Command(
53+
name = "solr",
54+
version = "Apache Solr version " + SolrVersion.LATEST_STRING,
55+
mixinStandardHelpOptions = true,
56+
commandListHeading = "\nCommands:\n",
57+
descriptionHeading = "Global options:\n",
58+
footer = {
59+
"",
60+
"SolrCloud example (embedded Zookeeper):",
61+
"",
62+
" ./solr start -c",
63+
"",
64+
"For more help on how to use Solr, head to https://solr.apache.org/"
65+
},
66+
usageHelpAutoWidth = true,
67+
defaultValueProvider = ZkTool.ZkHostDefaultValueProvider.class,
68+
subcommands = {StatusTool.class, HealthcheckTool.class, VersionTool.class, ZkTool.class})
5069
public class SolrCLI implements CLIO {
5170

5271
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
5372

73+
@picocli.CommandLine.Option(
74+
names = {"-v", "--version"},
75+
versionHelp = true,
76+
description = "Print version information and exit")
77+
boolean versionRequested;
78+
79+
@picocli.CommandLine.Option(
80+
names = {"-h", "--help"},
81+
usageHelp = true,
82+
description = "Display this help message")
83+
boolean helpRequested;
84+
5485
public static void exit(int exitStatus) {
5586
try {
5687
System.exit(exitStatus);
@@ -62,6 +93,25 @@ public static void exit(int exitStatus) {
6293

6394
/** Runs a tool. */
6495
public static void main(String[] args) throws Exception {
96+
if (EnvUtils.getPropertyAsBool("solr.picocli", true)) {
97+
CLIO.err("Using picocli");
98+
SSLConfigurationsFactory.current().init();
99+
picocli.CommandLine commandLine = new picocli.CommandLine(new SolrCLI());
100+
exit(commandLine.execute(args));
101+
} else {
102+
CLIO.err("DEBUG: Using commons-cli");
103+
exit(parseWithCommonsCli(args));
104+
}
105+
}
106+
107+
/**
108+
* Parses the command-line arguments passed by the user using Apache Commons CLI. This
109+
*
110+
* @param args the original command-line arguments
111+
* @deprecated Please use picocli
112+
*/
113+
@Deprecated(since = "9.9")
114+
public static int parseWithCommonsCli(String[] args) throws Exception {
65115
final boolean hasNoCommand =
66116
args == null || args.length == 0 || args[0] == null || args[0].trim().length() == 0;
67117
final boolean isHelpCommand = !hasNoCommand && Arrays.asList("-h", "--help").contains(args[0]);
@@ -117,15 +167,17 @@ public static void main(String[] args) throws Exception {
117167
System.exit(1);
118168
}
119169
CommandLine cli = parseCmdLine(tool, args);
120-
System.exit(tool.runTool(cli));
170+
return tool.runTool(cli);
121171
}
122172

173+
@Deprecated
123174
public static Tool findTool(String[] args) throws Exception {
124175
String toolType = args[0].trim().toLowerCase(Locale.ROOT);
125176
return newTool(toolType);
126177
}
127178

128-
public static CommandLine parseCmdLine(Tool tool, String[] args) {
179+
@Deprecated
180+
public static org.apache.commons.cli.CommandLine parseCmdLine(Tool tool, String[] args) {
129181
// the parser doesn't like -D props
130182
List<String> toolArgList = new ArrayList<>();
131183
List<String> dashDList = new ArrayList<>();
@@ -140,7 +192,7 @@ public static CommandLine parseCmdLine(Tool tool, String[] args) {
140192
String[] toolArgs = toolArgList.toArray(new String[0]);
141193

142194
// process command-line args to configure this application
143-
CommandLine cli = processCommandLineArgs(tool, toolArgs);
195+
org.apache.commons.cli.CommandLine cli = processCommandLineArgs(tool, toolArgs);
144196

145197
List<String> argList = cli.getArgList();
146198
argList.addAll(dashDList);
@@ -179,6 +231,7 @@ protected static void checkSslStoreSysProp(String solrInstallDir, String key) {
179231
}
180232

181233
// Creates an instance of the requested tool, using classpath scanning if necessary
234+
@Deprecated
182235
private static Tool newTool(String toolType) throws Exception {
183236
if ("healthcheck".equals(toolType)) return new HealthcheckTool();
184237
else if ("status".equals(toolType)) return new StatusTool();
@@ -232,7 +285,7 @@ private static Tool newTool(String toolType) throws Exception {
232285
* CLI option.
233286
*/
234287
public static String getOptionWithDeprecatedAndDefault(
235-
CommandLine cli, Option opt, Option deprecated, String def) {
288+
org.apache.commons.cli.CommandLine cli, Option opt, Option deprecated, String def) {
236289
String val = cli.getOptionValue(opt);
237290
if (val == null) {
238291
val = cli.getOptionValue(deprecated);
@@ -242,6 +295,7 @@ public static String getOptionWithDeprecatedAndDefault(
242295

243296
// TODO: SOLR-17429 - remove the custom logic when Commons CLI is upgraded and
244297
// makes stderr the default, or makes Option.toDeprecatedString() public.
298+
@Deprecated
245299
private static void deprecatedHandlerStdErr(Option o) {
246300
// Deprecated options without a description act as "stealth" options
247301
if (o.isDeprecated() && !o.getDeprecated().getDescription().isBlank()) {
@@ -256,10 +310,12 @@ private static void deprecatedHandlerStdErr(Option o) {
256310
}
257311

258312
/** Parses the command-line arguments passed by the user. */
259-
public static CommandLine processCommandLineArgs(Tool tool, String[] args) {
313+
@Deprecated
314+
public static org.apache.commons.cli.CommandLine processCommandLineArgs(
315+
Tool tool, String[] args) {
260316
Options options = tool.getOptions();
261317

262-
CommandLine cli = null;
318+
org.apache.commons.cli.CommandLine cli = null;
263319
try {
264320
cli =
265321
DefaultParser.builder()
@@ -296,6 +352,7 @@ public static CommandLine processCommandLineArgs(Tool tool, String[] args) {
296352
}
297353

298354
/** Prints tool help for a given tool */
355+
@Deprecated
299356
public static void printToolHelp(Tool tool) {
300357
HelpFormatter formatter = getFormatter();
301358
Options nonDeprecatedOptions = new Options();
@@ -314,13 +371,19 @@ public static void printToolHelp(Tool tool) {
314371
autoGenerateUsage);
315372
}
316373

374+
@Deprecated
317375
public static HelpFormatter getFormatter() {
318376
HelpFormatter formatter = HelpFormatter.builder().get();
319377
formatter.setWidth(120);
320378
return formatter;
321379
}
322380

323-
/** Scans Jar files on the classpath for Tool implementations to activate. */
381+
/**
382+
* Scans Jar files on the classpath for Tool implementations to activate.
383+
*
384+
* @deprecated With Picocli we no longer need to scan the classpath for Tool implementations?
385+
*/
386+
@Deprecated
324387
private static List<Class<? extends Tool>> findToolClassesInPackage(String packageName) {
325388
List<Class<? extends Tool>> toolClasses = new ArrayList<>();
326389
try {
@@ -344,6 +407,7 @@ private static List<Class<? extends Tool>> findToolClassesInPackage(String packa
344407
return toolClasses;
345408
}
346409

410+
@Deprecated
347411
private static Set<String> findClasses(String path, String packageName) throws Exception {
348412
Set<String> classes = new TreeSet<>();
349413
if (path.startsWith("file:") && path.contains("!")) {
@@ -402,6 +466,7 @@ public static String uptime(long uptimeMs) {
402466
numSeconds);
403467
}
404468

469+
@Deprecated
405470
private static void printHelp() {
406471

407472
print("Usage: solr COMMAND OPTIONS");

0 commit comments

Comments
 (0)