diff --git a/solr/core/src/java/org/apache/solr/cli/ConfigSetDownloadTool.java b/solr/core/src/java/org/apache/solr/cli/ConfigSetDownloadTool.java index 5f414e4c2fc..33d7727f6e2 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConfigSetDownloadTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ConfigSetDownloadTool.java @@ -66,6 +66,23 @@ public class ConfigSetDownloadTool extends ToolBase { @picocli.CommandLine.Mixin ConfigSetOptions configSetOpts; + @picocli.CommandLine.Option( + names = {"-d", "--conf-dir"}, + description = + """ + Local directory for configs. + The path to write the downloaded configuration set into. If just a name is supplied, `$SOLR_TIP/server/solr/configsets` will be the parent. An absolute path may be supplied as well. + + In either case, _pre-existing configurations at the destination will be overwritten_! + + **Examples:** + * `-d directory_under_configsets` + * `-d /path/to/configset/destination` + """, + required = true, + paramLabel = "DIR") + public String confDir; + public ConfigSetDownloadTool() { this(new DefaultToolRuntime()); } @@ -138,7 +155,7 @@ public int callTool() throws Exception { .withUrl(zkHost) .withTimeout(SolrZkClientTimeout.DEFAULT_ZK_CLIENT_TIMEOUT, TimeUnit.MILLISECONDS) .build()) { - doDownconfig(zkClient, zkHost, configSetOpts.confName, configSetOpts.confDir); + doDownconfig(zkClient, zkHost, configSetOpts.confName, confDir); return 0; } catch (Exception e) { log.error("Could not complete downconfig operation for reason: ", e); diff --git a/solr/core/src/java/org/apache/solr/cli/ConfigSetOptions.java b/solr/core/src/java/org/apache/solr/cli/ConfigSetOptions.java index 61eb657ff77..c5b2b1a77ad 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConfigSetOptions.java +++ b/solr/core/src/java/org/apache/solr/cli/ConfigSetOptions.java @@ -28,14 +28,17 @@ public class ConfigSetOptions { @CommandLine.Option( names = {"-n", "--conf-name"}, - description = "Configset name in ZooKeeper.", + description = + """ + Configset name in ZooKeeper. + Name of the configuration set under the "/configs" ZooKeeper node. + + You can see available configuration sets in the Admin UI via the Cloud screens. Choose Cloud → Tree → configs to see them. + + If a pre-existing configuration set is specified, it will be overwritten in ZooKeeper. + + **Example:** `-n myconfig` + """, required = true) public String confName; - - @CommandLine.Option( - names = {"-d", "--conf-dir"}, - description = "Local directory with configs.", - required = true, - paramLabel = "DIR") - public String confDir; } diff --git a/solr/core/src/java/org/apache/solr/cli/ConfigSetUploadTool.java b/solr/core/src/java/org/apache/solr/cli/ConfigSetUploadTool.java index b1c534bda45..69b902064f4 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConfigSetUploadTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ConfigSetUploadTool.java @@ -68,6 +68,23 @@ public class ConfigSetUploadTool extends ToolBase { @picocli.CommandLine.Mixin ConfigSetOptions configSetOpts; + @picocli.CommandLine.Option( + names = {"-d", "--conf-dir"}, + description = + """ + Local directory for configs. + The local directory of the configuration set to upload. It should have a `conf` directory immediately below it that in turn contains `solrconfig.xml` etc. + + If just a name is supplied, `$SOLR_TIP/server/solr/configsets` will be checked for this name. An absolute path may be supplied instead. + + **Examples:** + * `-d directory_under_configsets` + * `-d /path/to/configset/source` + """, + required = true, + paramLabel = "DIR") + public String confDir; + public ConfigSetUploadTool() { this(new DefaultToolRuntime()); } @@ -142,7 +159,7 @@ public int callTool() throws Exception { .withUrl(zkHost) .withTimeout(SolrZkClientTimeout.DEFAULT_ZK_CLIENT_TIMEOUT, TimeUnit.MILLISECONDS) .build()) { - doUpconfig(zkClient, zkHost, configSetOpts.confName, configSetOpts.confDir); + doUpconfig(zkClient, zkHost, configSetOpts.confName, confDir); return 0; } catch (Exception e) { log.error("Could not complete upconfig operation for reason: ", e); diff --git a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java index f6ccd7d3333..71ae5ec8f48 100755 --- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java +++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java @@ -109,8 +109,34 @@ public static void main(String[] args) throws Exception { } } + /** + * Truncates each option's description to its first line for interactive {@code --help} output. + * The remaining lines of the {@code description} array are reserved for the generated ref-guide. + * This customization is only installed on the interactive CLI command setup, so ref-guide + * generation, which runs the doc generator directly, still sees the full description. + */ + @VisibleForTesting + static void installFirstLineOnlyHelpFactory(picocli.CommandLine cmd) { + cmd.setHelpFactory( + (spec, colorScheme) -> + new picocli.CommandLine.Help(spec, colorScheme) { + @Override + public picocli.CommandLine.Help.IOptionRenderer createDefaultOptionRenderer() { + picocli.CommandLine.Help.IOptionRenderer base = super.createDefaultOptionRenderer(); + return (option, paramLabelRenderer, scheme) -> { + picocli.CommandLine.Help.Ansi.Text[][] rows = + base.render(option, paramLabelRenderer, scheme); + return rows.length <= 1 + ? rows + : new picocli.CommandLine.Help.Ansi.Text[][] {rows[0]}; + }; + } + }); + } + /** Propagates common settings to all subcommands. */ private static void propagateCommandSettings(picocli.CommandLine cmd) { + installFirstLineOnlyHelpFactory(cmd); for (picocli.CommandLine subcommand : cmd.getSubcommands().values()) { subcommand.getCommandSpec().defaultValueProvider(cmd.getCommandSpec().defaultValueProvider()); subcommand.getCommandSpec().usageMessage().width(cmd.getCommandSpec().usageMessage().width()); diff --git a/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java b/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java index d045ae35501..50cfcfed3cd 100644 --- a/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java +++ b/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java @@ -36,4 +36,27 @@ public void testUptime() { assertEquals( "106751991167 days, 7 hours, 12 minutes, 56 seconds", SolrCLI.uptime(Long.MAX_VALUE)); } + + @Test + public void testFirstLineOnlyHelpFactoryTruncatesMultiLineDescription() { + picocli.CommandLine cmd = new picocli.CommandLine(new MultiLineDescriptionCommand()); + + String baseline = cmd.getUsageMessage(); + assertTrue("baseline should include first line", baseline.contains("First line.")); + assertTrue("baseline should include second line", baseline.contains("Second line.")); + + SolrCLI.installFirstLineOnlyHelpFactory(cmd); + String truncated = cmd.getUsageMessage(); + assertTrue("truncated should include first line", truncated.contains("First line.")); + assertFalse("truncated should NOT include second line", truncated.contains("Second line.")); + assertFalse("truncated should NOT include third line", truncated.contains("Third line.")); + } + + @picocli.CommandLine.Command(name = "test") + private static class MultiLineDescriptionCommand { + @picocli.CommandLine.Option( + names = "--multi", + description = {"First line.", "Second line.", "Third line."}) + String multi; + } } diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-zk-downconfig.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-zk-downconfig.adoc index 980cc0de036..342566fcf6a 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-zk-downconfig.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-zk-downconfig.adoc @@ -50,10 +50,42 @@ Download a configset from ZooKeeper to the local filesystem. == Options *-d*, *--conf-dir*=_DIR_:: - *(required)* Local directory with configs. + *(required)* Local directory for configs. ++ +The path to write the downloaded configuration set into. If just a name is supplied, `$SOLR_TIP/server/solr/configsets` will be the parent. An absolute path may be supplied as well. ++ + ++ +In either case, _pre-existing configurations at the destination will be overwritten_! ++ + ++ +**Examples:** ++ +* `-d directory_under_configsets` ++ +* `-d /path/to/configset/destination` ++ + *-n*, *--conf-name*=__:: *(required)* Configset name in ZooKeeper. ++ +Name of the configuration set under the "/configs" ZooKeeper node. ++ + ++ +You can see available configuration sets in the Admin UI via the Cloud screens. Choose Cloud → Tree → configs to see them. ++ + ++ +If a pre-existing configuration set is specified, it will be overwritten in ZooKeeper. ++ + ++ +**Example:** `-n myconfig` ++ + *-s*, *--solr-url*=__:: Base Solr URL, which can be used to determine the zk-host if --zk-host is not known diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-zk-upconfig.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-zk-upconfig.adoc index e6a04d7063e..7353719867f 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-zk-upconfig.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-zk-upconfig.adoc @@ -50,10 +50,42 @@ Upload a configset from the local filesystem to ZooKeeper. == Options *-d*, *--conf-dir*=_DIR_:: - *(required)* Local directory with configs. + *(required)* Local directory for configs. ++ +The local directory of the configuration set to upload. It should have a `conf` directory immediately below it that in turn contains `solrconfig.xml` etc. ++ + ++ +If just a name is supplied, `$SOLR_TIP/server/solr/configsets` will be checked for this name. An absolute path may be supplied instead. ++ + ++ +**Examples:** ++ +* `-d directory_under_configsets` ++ +* `-d /path/to/configset/source` ++ + *-n*, *--conf-name*=__:: *(required)* Configset name in ZooKeeper. ++ +Name of the configuration set under the "/configs" ZooKeeper node. ++ + ++ +You can see available configuration sets in the Admin UI via the Cloud screens. Choose Cloud → Tree → configs to see them. ++ + ++ +If a pre-existing configuration set is specified, it will be overwritten in ZooKeeper. ++ + ++ +**Example:** `-n myconfig` ++ + *-s*, *--solr-url*=__:: Base Solr URL, which can be used to determine the zk-host if --zk-host is not known