Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/bin-solr-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ jobs:
- name: Test the bin/solr script
run: ./gradlew integrationTests

# Reuses the distribution built above, so this only costs the curated suite run.
- name: Test the bin/solr script with the experimental picocli CLI
- name: Test the bin/solr script with PicoCLI
Comment thread
janhoy marked this conversation as resolved.
run: ./gradlew integrationTestsPicocli

- name: Archive logs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
title: >
An experimental re-implementation of the `bin/solr` command line interface, built on picocli,
is now included. It is disabled by default and is enabled with `SOLR_PICOCLI=true`. Only some
commands have been migrated so far, and its options may change between releases. See the
"Experimental picocli Command Line Interface" page in the Reference Guide.
Migration of the `bin/solr` command line interface, to picocli.
It is enabled by default and can be disabled with `SOLR_PICOCLI=false`. See the
"PicoCLI Command Line Interface" page in the Reference Guide.
type: added
authors:
- name: Jan Høydahl
url: https://home.apache.org/phonebook.html?uid=janhoy
- name: Serhiy Bzhezytskyy
- name: Jalaz Kumar
nick: jaykay12
- name: Eric Pugh
links:
- name: SOLR-17697
url: https://issues.apache.org/jira/browse/SOLR-17697
Expand All @@ -35,3 +35,5 @@ links:
url: https://issues.apache.org/jira/browse/SOLR-18517
- name: SOLR-18515
url: https://issues.apache.org/jira/browse/SOLR-18515
- name: SOLR-18561
url: https://issues.apache.org/jira/browse/SOLR-18561
11 changes: 0 additions & 11 deletions dev-docs/ref-guide/antora.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,6 @@ The new command will automatically appear in the generated pages, in the navigat
`pages/cli/index.adoc` is the only hand-written page in that directory; everything matching `solr-*.adoc` is generated and must not be edited by hand.
`solr-control-script-reference.adoc` documents the default (commons-cli) implementation and should not gain per-command links to the generated pages while the picocli implementation is experimental.

=== What a tool migration should include

When migrating a tool to picocli:

* A `*PicocliTest` subclass of the tool's existing test that overrides only the invocation strategy, so every case runs on both implementations. See `ZkSubcommandsPicocliTest` for the pattern.
* The tool's `.bats` file added to `integrationTestsPicocli` in `solr/packaging/build.gradle`, but only once *every* command that suite invokes has been migrated, not just the one under test.
`test_auth.bats`, for example, uses `solr assert` to wait for startup, so it cannot be added until the assert command is migrated.
Be aware that a failure part-way through that suite is especially awkward: `solr auth enable` appends `SOLR_AUTH_TYPE` and `SOLR_AUTHENTICATION_OPTS` to the `solr.in.sh` of the *built distribution* under `solr/packaging/build/`, so an aborted run leaves every later `bin/solr` invocation trying to authenticate.
If BATS runs start hanging for no apparent reason, check that file, and delete the distribution directory to force `installFullDist` to recreate it.
* A `gradlew :solr:solr-ref-guide:generateCliDocs` run, with the result committed.
* The tool registered in `SolrCLI`'s `subcommands` only once `callTool()` actually works; `SolrCLIPicocliTest` enforces the rules that apply to every registered command.
Comment thread
janhoy marked this conversation as resolved.

== Building the HTML Site

Expand Down
6 changes: 3 additions & 3 deletions solr/bin/solr
Original file line number Diff line number Diff line change
Expand Up @@ -828,10 +828,10 @@ if [ $# -gt 0 ]; then
shift 2
;;
-h|--help)
if [[ "${SOLR_PICOCLI:-}" == "true" ]]; then
run_tool "$SCRIPT_CMD" --help
if [[ "${SOLR_PICOCLI:-}" == "false" ]]; then
print_usage "$SCRIPT_CMD"
else
print_usage "$SCRIPT_CMD"
run_tool "$SCRIPT_CMD" --help
fi
exit 0
;;
Expand Down
4 changes: 2 additions & 2 deletions solr/bin/solr.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ IF "%1"=="-h" goto check_picocli_help
goto after_help_check

:check_picocli_help
IF "%SOLR_PICOCLI%"=="true" goto run_picocli_help
goto usage
IF "%SOLR_PICOCLI%"=="false" goto usage
goto run_picocli_help

:run_picocli_help
"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^
Expand Down
2 changes: 1 addition & 1 deletion solr/core/src/java/org/apache/solr/cli/SolrCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public static void exit(int exitStatus) {

/** Runs a tool. */
public static void main(String[] args) throws Exception {
if (EnvUtils.getPropertyAsBool("solr.picocli", false)) {
if (EnvUtils.getPropertyAsBool("solr.picocli", true)) {
SSLConfigurationsFactory.current().init();
picocli.CommandLine commandLine = new picocli.CommandLine(new SolrCLI());
propagateCommandSettings(commandLine);
Expand Down
32 changes: 22 additions & 10 deletions solr/packaging/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -338,26 +338,38 @@ def configureBatsTask(BatsTask task, String outputName, boolean usePicocli) {
task.environment TEST_OUTPUT_DIR: integrationTestOutput
task.environment TEST_FAILURE_DIR: solrTestFailuresDir
task.environment BATS_LIB_PREFIX: batsLibsDir
if (usePicocli) {
task.environment SOLR_PICOCLI: 'true'
if (!usePicocli) {
task.environment SOLR_PICOCLI: 'false'
}
}

// TODO: Remove this when cleaning up commons-cli
task integrationTests(type: BatsTask) {
description = 'Runs the BATS suites for the CLI powered by commons-cli.'
configureBatsTask(it, 'test-output', false)
}

// The same suites run against the experimental picocli CLI. Deliberately a curated list rather
// than the whole suite, so the run stays short. A change that ports another tool to picocli
// should add that tool's .bats file here.
// The same suites run against the picocli CLI.
task integrationTestsPicocli(type: BatsTask) {
description = 'Runs the BATS suites for the migrated commands against the experimental picocli CLI.'
description = 'Runs the BATS suites for the CLI powered by PicoCLI.'
configureBatsTask(it, 'test-output-picocli', true)
// A suite belongs here only when every command it invokes has been migrated, not merely the
// command under test. test_auth.bats, for example, uses `solr assert` to wait for startup, so
// it cannot join until the assert command is migrated. test_help.bats asserts the exact wording
// of the commons-cli help output, which the picocli implementation words differently.
// TODO: Remove these explicit files entry from here after fixing 4 remaining bats file
testFiles = [
'test/test_adminconsole_urls.bats',
'test/test_assert.bats',
'test/test_bats.bats',
'test/test_compression.bats',
'test/test_config.bats',
'test/test_create_collection.bats',
'test/test_example.bats',
'test/test_export.bats',
'test/test_opennlp.bats',
'test/test_placement_plugin.bats',
'test/test_rolling_upgrade.bats',
'test/test_snapshots.bats',
'test/test_ssl.bats',
'test/test_start_solr.bats',
'test/test_zz_cleanup.bats',

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are 4 bats that requires fix, I will be raising a follow-up PR for the same, for now added a Todo here & adding the remaining bats.

this takes us from 41 -> 92 assertions now.

Image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this means we now run the entire BATS suite for picocli, right?

@jaykay12 jaykay12 Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are running 26/30 bats suite for now, the 4 that are not in the list: tests_basic_auth, test_help, test_post & test_stream. I will work on debugging & fixing in a quick follow-up PR & then those will also get added. we will then remove this Todo & then we can say all 30 BATs suite runs for PicoCLI.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@janhoy Here it is: #5204

'test/test_version.bats',
'test/test_status.bats',
'test/test_create.bats',
Expand Down
19 changes: 5 additions & 14 deletions solr/solr-ref-guide/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
* limitations under the License.
*/


import groovy.json.JsonOutput
import javax.inject.Inject
import org.gradle.process.ExecOperations
import org.apache.tools.ant.util.TeeOutputStream

apply plugin: 'java'
Expand Down Expand Up @@ -592,15 +592,6 @@ def ASF_LICENSE_HEADER = """\
// under the License.
"""

def EXPERIMENTAL_NOTICE = """\
[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====
"""

Comment thread
janhoy marked this conversation as resolved.
def DO_NOT_EDIT_NOTICE = """\
//
// DO NOT EDIT -- this page is auto-generated from picocli annotations.
Expand Down Expand Up @@ -719,7 +710,7 @@ String markRequiredOptionsAndArgs(String content) {
// Post-process a raw ManPageGenerator AsciiDoc file for Antora compatibility.
// The title lives inside the man-section-header block, so we replace the whole
// header block with an Antora-compatible page title + attributes.
String postProcessCliManPage(File rawFile, Set stems, String asfHeader, String doNotEditNotice, String experimentalNotice) {
String postProcessCliManPage(File rawFile, Set stems, String asfHeader, String doNotEditNotice) {
def content = rawFile.text
def baseName = rawFile.name.replace('.adoc', '')
def newTitle = cliFileNameToTitle(baseName, stems)
Expand Down Expand Up @@ -775,7 +766,7 @@ String postProcessCliManPage(File rawFile, Set stems, String asfHeader, String d

// Inserted last, after the blanket 'xref:solr-' -> 'xref:cli/solr-' rewrite above, which would
// otherwise redirect this notice's own link into pages/cli/.
content = content.replace(":page-toclevels: 2\n", ":page-toclevels: 2\n\n" + experimentalNotice)
content = content.replace(":page-toclevels: 2\n", ":page-toclevels: 2\n\n")

return asfHeader + doNotEditNotice + "\n" + content.stripTrailing() + "\n"
}
Expand Down Expand Up @@ -862,7 +853,7 @@ task generateCliDocs {
def stems = rawFiles.collect { it.name.replace('.adoc', '') } as Set

rawFiles.each { rawFile ->
def processed = postProcessCliManPage(rawFile, stems, ASF_LICENSE_HEADER, DO_NOT_EDIT_NOTICE, EXPERIMENTAL_NOTICE)
def processed = postProcessCliManPage(rawFile, stems, ASF_LICENSE_HEADER, DO_NOT_EDIT_NOTICE)
new File(destDir, rawFile.name).text = processed
}

Expand Down Expand Up @@ -919,7 +910,7 @@ task checkCliDocsUpToDate {
def issues = []

rawFiles.each { rawFile ->
def processed = postProcessCliManPage(rawFile, stems, ASF_LICENSE_HEADER, DO_NOT_EDIT_NOTICE, EXPERIMENTAL_NOTICE)
def processed = postProcessCliManPage(rawFile, stems, ASF_LICENSE_HEADER, DO_NOT_EDIT_NOTICE)
def committed = new File(committedDir, rawFile.name)
if (!committed.exists()) {
issues << "MISSING committed file (new command): ${rawFile.name}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
.Deployment Guide

* xref:solr-control-script-reference.adoc[]
** xref:cli/index.adoc[Experimental picocli CLI]
** xref:cli/index.adoc[CLI command reference]
// CLI-DOCS-START
*** xref:cli/solr-api.adoc[api]
*** xref:cli/solr-assert.adoc[assert]
Expand Down
46 changes: 19 additions & 27 deletions solr/solr-ref-guide/modules/deployment-guide/pages/cli/index.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
= Experimental picocli Command Line Interface
= Command Line Interface
:page-toclevels: 2
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
Expand All @@ -17,42 +17,34 @@
// specific language governing permissions and limitations
// under the License.

Solr is migrating the `bin/solr` command line tool from Apache Commons CLI to https://picocli.info/[picocli].
While that work is in progress, both implementations ship together and the picocli one can be enabled on request.
The `bin/solr` command line tool is built on https://picocli.info/[picocli].
This page and the per-command pages linked below are the references for its commands and options.
Run `bin/solr <command> --help` for the same information on the command line.

[WARNING]
====
The picocli command line interface is *experimental* and disabled by default.
== Falling back to the legacy CLI

* Only some commands have been migrated so far.
* Options, defaults and error messages may change without notice between releases.
* Where this implementation and the default one differ, xref:solr-control-script-reference.adoc[] describes what `bin/solr` actually does by default.
The previous Apache Commons CLI implementation still ships with Solr.
Use it only as an escape hatch if you run into a problem with the default CLI, and please report the problem to the Solr project.
Its options and output differ in places; see xref:solr-control-script-reference.adoc[] for its documentation.

Do not depend on it in scripts or automation yet.
====

== Enabling It

Set `SOLR_PICOCLI` in your `solr.in.sh` (or `solr.in.cmd` on Windows):
To switch, set `SOLR_PICOCLI` in your `solr.in.sh` (or `solr.in.cmd` on Windows):

[source,bash]
----
SOLR_PICOCLI=true
SOLR_PICOCLI=false
----

Or set the equivalent system property for a single invocation:

[source,bash]
----
SOLR_TOOL_OPTS="-Dsolr.picocli=true" bin/solr status
SOLR_TOOL_OPTS="-Dsolr.picocli=false" bin/solr status
----

Unset it, or set it to anything other than `true`, to return to the default implementation.

== Migrated Commands
== Commands

The commands below have been migrated and have a reference page generated from their source annotations.
Any command not listed here is unavailable when the picocli implementation is enabled, and reports an unmatched argument.
Each command has a reference page generated from its source annotations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An end user won't know what a "source annotation" is. The ref guide is for end users, we should describe what they see, the commands they write and the response they get back, not code-level things.


// CLI-DOCS-TABLE-START
[cols="1",options="header"]
Expand Down Expand Up @@ -103,18 +95,18 @@ Any command not listed here is unavailable when the picocli implementation is en
|===
// CLI-DOCS-TABLE-END

== Known Limitations
== Migration Changes

In addition to the commands that have not been migrated yet:
These are the changes in default CLI behavior as compared to 9.x and 10.1.

* On a sub-command, `-v` means `--verbose`; only the top-level `bin/solr` accepts `-v` as a request for the version.
* `bin/solr config` has no `-v` short form for `--value`, because `-v` means `--verbose`; use `--value`.
The default implementation accepts `-v` for it.
The legacy CLI accepts `-v` for it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's dangerous to use a term like legacy, in this context we could perhaps say that before Solr 10.2 -v was a short-hand for value for the config command, but not any more.

The legacy comment is general for any other place it may have been used.

Also, I'm not sure that "migration changes" even belong in this doc page. It will duplicate the upgrade notes in major-changes-in-solr-10, section 10.2. so I'd prefer if we just do a WARNING callout on this page with a link to that upgrade notes section, and document all deliberate breaking changes for PicoCLI there only.

* `--fail-on-exists` on `bin/solr zk mkroot` treats the option as set whenever it is present, whatever value follows it.
This matches the default implementation, but means `--fail-on-exists false` does not disable the check.
* Error messages for invalid or mutually exclusive options are worded differently from the default implementation.
This matches the legacy CLI, but means `--fail-on-exists false` does not disable the check.
* Error messages for invalid or mutually exclusive options are worded differently from the legacy CLI.
* Usage and help output is laid out differently throughout, so anything parsing the output of `--help` will need adjusting.
* Typing a `zk` sub-command without the `zk` prefix, for example `bin/solr ls`, reports an unmatched argument rather than the reminder the default implementation prints.
* Typing a `zk` sub-command without the `zk` prefix, for example `bin/solr ls`, reports an unmatched argument rather than the reminder the legacy CLI prints.
That syntax was removed in Solr 9; use `bin/solr zk ls`.

== Reporting Problems
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
= bin/solr api
:page-toclevels: 2

[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====

// tag::picocli-generated-man-section-synopsis[]
== Synopsis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
= bin/solr assert
:page-toclevels: 2

[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====

// tag::picocli-generated-man-section-synopsis[]
== Synopsis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
= bin/solr auth
:page-toclevels: 2

[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====

// tag::picocli-generated-man-section-synopsis[]
== Synopsis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
= bin/solr cluster
:page-toclevels: 2

[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====

// tag::picocli-generated-man-section-synopsis[]
== Synopsis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
= bin/solr config
:page-toclevels: 2

[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====

// tag::picocli-generated-man-section-synopsis[]
== Synopsis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
= bin/solr create
:page-toclevels: 2

[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====

// tag::picocli-generated-man-section-synopsis[]
== Synopsis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
= bin/solr delete
:page-toclevels: 2

[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====

// tag::picocli-generated-man-section-synopsis[]
== Synopsis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@
= bin/solr export
:page-toclevels: 2

[WARNING]
====
This page documents the *experimental* picocli implementation of `bin/solr`, which is not enabled by default.
For what `bin/solr` does by default, see xref:solr-control-script-reference.adoc[].
See xref:cli/index.adoc[] to enable this implementation and for its known limitations.
====

// tag::picocli-generated-man-section-synopsis[]
== Synopsis
Expand Down
Loading
Loading