This is an automated email from the ASF dual-hosted git repository.
epugh pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_10x by this push:
new e3d0064289d SOLR-18118: Add in --prompt-inputs to bin/solr start -e
cloud to programatically respond to input prompts (#4127)
e3d0064289d is described below
commit e3d0064289dcaf88c5d979dd56d68145ee72a872
Author: Eric Pugh <[email protected]>
AuthorDate: Wed Feb 18 06:05:55 2026 -0500
SOLR-18118: Add in --prompt-inputs to bin/solr start -e cloud to
programatically respond to input prompts (#4127)
Adds a non-interactive way to run bin/solr start -e cloud by supplying
ordered prompt answers on the command line, enabling scripted/automated cluster
startup while keeping existing interactive behavior available.
(cherry picked from commit b71c872c35b1a12551e3d9b832c1ef9c40a1ea0a)
---
changelog/unreleased/SOLR-18118.yml | 9 ++
solr/bin/solr | 24 +++--
solr/bin/solr.cmd | 22 +++--
.../java/org/apache/solr/cli/RunExampleTool.java | 56 ++++++++++-
.../org/apache/solr/cli/TestSolrCLIRunExample.java | 110 +++++++++++++++++++++
.../pages/solr-control-script-reference.adoc | 89 ++++++++++-------
6 files changed, 256 insertions(+), 54 deletions(-)
diff --git a/changelog/unreleased/SOLR-18118.yml
b/changelog/unreleased/SOLR-18118.yml
new file mode 100644
index 00000000000..e3d703091ff
--- /dev/null
+++ b/changelog/unreleased/SOLR-18118.yml
@@ -0,0 +1,9 @@
+# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
+title: Script creating a cluster using bin/solr start -e cloud with
--prompt-inputs option.
+type: added # added, changed, fixed, deprecated, removed, dependency_update,
security, other
+authors:
+ - name: Eric Pugh
+ - name: Rahul Goswami
+links:
+ - name: SOLR-18118
+ url: https://issues.apache.org/jira/browse/SOLR-18118
diff --git a/solr/bin/solr b/solr/bin/solr
index ec7f596144d..eaa417ca90d 100755
--- a/solr/bin/solr
+++ b/solr/bin/solr
@@ -407,12 +407,6 @@ function print_usage() {
echo " --data-home <dir> Sets the solr.data.home system property,
where Solr will store index data in <instance_dir>/data subdirectories."
echo " If not set, Solr uses solr.solr.home for
config and data."
echo ""
- echo " -e/--example <name> Name of the example to run; available
examples:"
- echo " cloud: SolrCloud example"
- echo " techproducts: Comprehensive example illustrating many of
Solr's core capabilities"
- echo " schemaless: Schema-less example (schema is inferred
from data during indexing)"
- echo " films: Example of starting with _default
configset and adding explicit fields dynamically"
- echo ""
echo " --jvm-opts <jvmParams> Additional parameters to pass to the JVM
when starting Solr, such as to setup"
echo " Java debug options. For example, to enable
a Java debugger to attach to the Solr JVM"
echo " you could pass: --jvm-opts
\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=18983\""
@@ -423,7 +417,15 @@ function print_usage() {
echo " you could pass: -j
\"--include-jetty-dir=/etc/jetty/custom/server/\""
echo " In most cases, you should wrap the
additional parameters in double quotes."
echo ""
- echo " -y/--no-prompt Don't prompt for input; accept all defaults
when running examples that accept user input"
+ echo " -e/--example <name> Name of the example to run; available
examples:"
+ echo " cloud: SolrCloud example"
+ echo " techproducts: Comprehensive example illustrating many of
Solr's core capabilities"
+ echo " schemaless: Schema-less example (schema is inferred
from data during indexing)"
+ echo " films: Example of starting with _default
configset and adding explicit fields dynamically"
+ echo ""
+ echo " -y/--no-prompt Don't prompt for input; accept all defaults
when running examples that accept user input."
+ echo ""
+ echo " --prompt-inputs <values> Don't prompt for input; comma delimited
list of inputs read when running examples that accept user input."
echo ""
echo " --force If attempting to start Solr as the root
user, the script will exit with a warning that running Solr as \"root\" can
cause problems."
echo " It is possible to override this warning
with the '--force' parameter."
@@ -817,6 +819,14 @@ if [ $# -gt 0 ]; then
PASS_TO_RUN_EXAMPLE+=("--no-prompt")
shift
;;
+ --prompt-inputs)
+ if [[ -z "$2" || "${2:0:1}" == "-" ]]; then
+ print_usage "$SCRIPT_CMD" "Prompt values are required when using the
$1 option!"
+ exit 1
+ fi
+ PASS_TO_RUN_EXAMPLE+=("--prompt-inputs" "$2")
+ shift 2
+ ;;
--verbose)
verbose=true
SOLR_LOG_LEVEL=DEBUG
diff --git a/solr/bin/solr.cmd b/solr/bin/solr.cmd
index 52be92ed3de..e30cc4416fa 100755
--- a/solr/bin/solr.cmd
+++ b/solr/bin/solr.cmd
@@ -325,12 +325,6 @@ goto err
@echo --data-home dir Sets the solr.data.home system property, where Solr
will store index data in ^<instance_dir^>/data subdirectories.
@echo If not set, Solr uses solr.solr.home for both config
and data.
@echo.
-@echo -e/--example name Name of the example to run; available examples:
-@echo cloud: SolrCloud example
-@echo techproducts: Comprehensive example illustrating many of Solr's
core capabilities
-@echo schemaless: Schema-less example (schema is inferred from data
during indexing)
-@echo films: Example of starting with _default configset and
defining explicit fields dynamically
-@echo.
@echo --jvm-opts opts Additional parameters to pass to the JVM when starting
Solr, such as to setup
@echo Java debug options. For example, to enable a Java
debugger to attach to the Solr JVM
@echo you could pass: --jvm-opts
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=18983"
@@ -341,8 +335,16 @@ goto err
@echo you could pass: -j
"--include-jetty-dir=/etc/jetty/custom/server/"
@echo In most cases, you should wrap the additional parameters
in double quotes.
@echo.
+@echo -e/--example name Name of the example to run; available examples:
+@echo cloud: SolrCloud example
+@echo techproducts: Comprehensive example illustrating many of Solr's
core capabilities
+@echo schemaless: Schema-less example (schema is inferred from data
during indexing)
+@echo films: Example of starting with _default configset and
defining explicit fields dynamically
+@echo.
@echo -y/--no-prompt Don't prompt for input; accept all defaults when
running examples that accept user input
@echo.
+@echo --prompt-inputs values Don't prompt for input; comma delimited list of
inputs read when running examples that accept user input.
+@echo.
@echo --verbose and -q/--quiet Verbose or quiet logging. Sets default log
level to DEBUG or WARN instead of INFO
@echo.
goto done
@@ -399,6 +401,7 @@ IF "%1"=="-j" goto set_addl_jetty_config
IF "%1"=="--jettyconfig" goto set_addl_jetty_config
IF "%1"=="-y" goto set_noprompt
IF "%1"=="--no-prompt" goto set_noprompt
+IF "%1"=="--prompt-inputs" goto set_prompt_inputs
REM Skip stop arg parsing if not stop command
IF NOT "%SCRIPT_CMD%"=="stop" goto parse_general_args
@@ -695,6 +698,13 @@ set "PASS_TO_RUN_EXAMPLE=--no-prompt !PASS_TO_RUN_EXAMPLE!"
SHIFT
goto parse_args
+:set_prompt_inputs
+set "PASS_TO_RUN_EXAMPLE=--prompt-inputs %~2 !PASS_TO_RUN_EXAMPLE!"
+
+SHIFT
+SHIFT
+goto parse_args
+
REM Handle invalid arguments passed to special commands (start, stop, restart)
:invalid_cmd_line
@echo.
diff --git a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
index 9fcd71c911d..b5b21f6450f 100644
--- a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
@@ -73,6 +73,16 @@ public class RunExampleTool extends ToolBase {
"Don't prompt for input; accept all defaults when running
examples that accept user input.")
.build();
+ private static final Option PROMPT_INPUTS_OPTION =
+ Option.builder()
+ .longOpt("prompt-inputs")
+ .hasArg()
+ .argName("VALUES")
+ .desc(
+ "Provide comma-separated values for prompts. Same as --no-prompt
but uses provided values instead of defaults. "
+ + "Example: --prompt-inputs
3,8983,8984,8985,\"gettingstarted\",2,2,_default")
+ .build();
+
private static final Option EXAMPLE_OPTION =
Option.builder("e")
.longOpt("example")
@@ -176,6 +186,7 @@ public class RunExampleTool extends ToolBase {
protected Path exampleDir;
protected Path solrHomeDir;
protected String urlScheme;
+ private boolean usingPromptInputs = false;
/** Default constructor used by the framework when running as a command-line
application. */
public RunExampleTool(ToolRuntime runtime) {
@@ -197,6 +208,7 @@ public class RunExampleTool extends ToolBase {
public Options getOptions() {
return super.getOptions()
.addOption(NO_PROMPT_OPTION)
+ .addOption(PROMPT_INPUTS_OPTION)
.addOption(EXAMPLE_OPTION)
.addOption(SCRIPT_OPTION)
.addOption(SERVER_DIR_OPTION)
@@ -214,6 +226,12 @@ public class RunExampleTool extends ToolBase {
@Override
public void runImpl(CommandLine cli) throws Exception {
+ if (cli.hasOption(NO_PROMPT_OPTION) &&
cli.hasOption(PROMPT_INPUTS_OPTION)) {
+ throw new IllegalArgumentException(
+ "Cannot use both --no-prompt and --prompt-inputs options together. "
+ + "Use --no-prompt to accept defaults, or --prompt-inputs to
provide specific values.");
+ }
+
this.urlScheme = cli.getOptionValue(URL_SCHEME_OPTION, "http");
String exampleType = cli.getOptionValue(EXAMPLE_OPTION);
@@ -515,6 +533,7 @@ public class RunExampleTool extends ToolBase {
protected void runCloudExample(CommandLine cli) throws Exception {
+ usingPromptInputs = cli.hasOption(PROMPT_INPUTS_OPTION);
boolean prompt = !cli.hasOption(NO_PROMPT_OPTION);
int numNodes = 2;
int[] cloudPorts = new int[] {8983, 7574, 8984, 7575};
@@ -530,10 +549,24 @@ public class RunExampleTool extends ToolBase {
echo("\nWelcome to the SolrCloud example!\n");
- Scanner readInput = prompt ? new Scanner(userInput,
StandardCharsets.UTF_8) : null;
+ Scanner readInput = null;
+ if (usingPromptInputs) {
+ // Create a scanner from the provided prompts
+ String promptsValue = cli.getOptionValue(PROMPT_INPUTS_OPTION);
+ InputStream promptsStream =
+ new
java.io.ByteArrayInputStream(promptsValue.getBytes(StandardCharsets.UTF_8));
+ readInput = new Scanner(promptsStream, StandardCharsets.UTF_8);
+ readInput.useDelimiter(",");
+ prompt = true; // Enable prompting code path, but reading from prompts
instead of user
+ } else if (prompt) {
+ readInput = new Scanner(userInput, StandardCharsets.UTF_8);
+ }
+
if (prompt) {
- echo(
- "This interactive session will help you launch a SolrCloud cluster
on your local workstation.");
+ if (!usingPromptInputs) {
+ echo(
+ "This interactive session will help you launch a SolrCloud cluster
on your local workstation.");
+ }
// get the number of nodes to start
numNodes =
@@ -1121,9 +1154,24 @@ public class RunExampleTool extends ToolBase {
protected String prompt(Scanner s, String prompt, String defaultValue) {
echo(prompt);
- String nextInput = s.nextLine();
+ String nextInput;
+ if (usingPromptInputs) {
+ // Reading from prompts option - use next() instead of nextLine()
+ nextInput = s.hasNext() ? s.next() : null;
+ // Echo the value being used from prompts
+ if (nextInput != null) {
+ echo(nextInput);
+ }
+ } else {
+ // Reading from user input - use nextLine()
+ nextInput = s.nextLine();
+ }
if (nextInput != null) {
nextInput = nextInput.trim();
+ // Remove quotes if present (for values like "gettingstarted")
+ if (nextInput.startsWith("\"") && nextInput.endsWith("\"")) {
+ nextInput = nextInput.substring(1, nextInput.length() - 1);
+ }
if (nextInput.isEmpty()) nextInput = null;
}
return (nextInput != null) ? nextInput : defaultValue;
diff --git a/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
b/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
index db26383eb7f..298bbfb0644 100644
--- a/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
+++ b/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java
@@ -525,6 +525,116 @@ public class TestSolrCLIRunExample extends SolrTestCaseJ4
{
executor.execute(org.apache.commons.exec.CommandLine.parse("bin/solr stop
-p " + bindPort));
}
+ /**
+ * Test the --prompt-inputs option that allows providing all prompt values
as a comma-separated
+ * string without requiring interactive input.
+ */
+ @Test
+ public void testSolrCloudExampleWithPrompts() throws Exception {
+ Path solrHomeDir = ExternalPaths.SERVER_HOME;
+ if (!Files.isDirectory(solrHomeDir))
+ fail(solrHomeDir + " not found and is required to run this test!");
+
+ Path solrExampleDir = createTempDir();
+ Path solrServerDir = solrHomeDir.getParent();
+
+ int bindPort = -1;
+ try (ServerSocket socket = new ServerSocket(0)) {
+ bindPort = socket.getLocalPort();
+ }
+
+ String collectionName = "testCloudExampleWithPrompts";
+
+ // Provide all prompt values via --prompt-inputs option:
+ // numNodes, port1, collectionName, numShards, replicationFactor,
configName
+ String promptsValue = "1," + bindPort + ",\"" + collectionName +
"\",2,2,_default";
+
+ String[] toolArgs =
+ new String[] {
+ "--example",
+ "cloud",
+ "--server-dir",
+ solrServerDir.toString(),
+ "--example-dir",
+ solrExampleDir.toString(),
+ "--prompt-inputs",
+ promptsValue
+ };
+
+ // capture tool output to stdout
+ CLITestHelper.TestingRuntime runtime = new
CLITestHelper.TestingRuntime(true);
+
+ RunExampleExecutor executor = new RunExampleExecutor();
+ closeables.add(executor);
+
+ RunExampleTool tool = new RunExampleTool(executor, System.in, runtime);
+ try {
+ tool.runTool(SolrCLI.processCommandLineArgs(tool, toolArgs));
+ } catch (Exception e) {
+ System.err.println(
+ "RunExampleTool failed due to: "
+ + e
+ + "; stdout from tool prior to failure: "
+ + runtime.getOutput());
+ throw e;
+ }
+
+ String toolOutput = runtime.getOutput();
+
+ // verify Solr is running on the expected port and verify the collection
exists
+ String solrUrl = "http://localhost:" + bindPort + "/solr";
+ if (!CLIUtils.safeCheckCollectionExists(solrUrl, collectionName, null)) {
+ fail(
+ "After running Solr cloud example with --prompt-inputs, test
collection '"
+ + collectionName
+ + "' not found in Solr at: "
+ + solrUrl
+ + "; tool output: "
+ + toolOutput);
+ }
+
+ // verify the collection was created with the specified parameters
+ try (CloudSolrClient cloudClient =
+ new RandomizingCloudSolrClientBuilder(
+
Collections.singletonList(executor.solrCloudCluster.getZkServer().getZkAddress()),
+ Optional.empty())
+ .withDefaultCollection(collectionName)
+ .build()) {
+
+ // index some test docs to verify the collection works
+ int numDocs = 5;
+ for (int d = 0; d < numDocs; d++) {
+ SolrInputDocument doc = new SolrInputDocument();
+ doc.setField("id", "doc" + d);
+ doc.setField("test_s", "prompts");
+ cloudClient.add(doc);
+ }
+ cloudClient.commit();
+
+ QueryResponse qr = cloudClient.query(new SolrQuery("test_s:prompts"));
+ assertEquals(
+ "Expected "
+ + numDocs
+ + " docs in the "
+ + collectionName
+ + " collection created via --prompts",
+ numDocs,
+ qr.getResults().getNumFound());
+ }
+
+ // Verify output contains the prompts values
+ assertTrue(
+ "Tool output should contain the collection name",
toolOutput.contains(collectionName));
+
+ // delete the collection
+ DeleteTool deleteTool = new DeleteTool(runtime);
+ String[] deleteArgs = new String[] {"--name", collectionName,
"--solr-url", solrUrl};
+ deleteTool.runTool(SolrCLI.processCommandLineArgs(deleteTool, deleteArgs));
+
+ // stop the test instance
+ executor.execute(org.apache.commons.exec.CommandLine.parse("bin/solr stop
-p " + bindPort));
+ }
+
@Test
public void testFailExecuteScript() throws Exception {
Path solrHomeDir = ExternalPaths.SERVER_HOME;
diff --git
a/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
b/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
index 577c566eb4a..a7348059cc2 100644
---
a/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
+++
b/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
@@ -106,27 +106,6 @@ When running multiple instances of Solr on the same host,
it is more common to u
+
*Example*: `bin/solr start --server-dir newServerDir`
-`-e <name>`::
-+
-[%autowidth,frame=none]
-|===
-|Optional |Default: none
-|===
-+
-Start Solr with an example configuration.
-These examples are provided to help you get started faster with Solr
generally, or just try a specific feature.
-+
-The available options are:
-
-* `cloud`: SolrCloud example
-* `techproducts`: Comprehensive example illustrating many of Solr's core
capabilities
-* `schemaless`: Schema-less example (schema is inferred from data during
indexing)
-* `films`: Example of starting with _default configset and adding explicit
fields dynamically
-+
-See the section <<Running with Example Configurations>> below for more details
on the example configurations.
-+
-*Example*: `bin/solr start -e schemaless`
-
`-f`::
+
[%autowidth,frame=none]
@@ -162,20 +141,6 @@ Sets the min (`-Xms`) and max (`-Xmx`) heap size for the
JVM running Solr.
+
*Example*: `bin/solr start -m 4g` results in `-Xms4g -Xmx4g` settings.
-`--no-prompt`::
-+
-[%autowidth,frame=none]
-|===
-|Optional |Default: none
-|===
-+
-Don't prompt for input; accept all defaults when running examples that accept
user input.
-+
-For example, when using the "cloud" example, an interactive session guides you
through several options for your SolrCloud cluster.
-If you want to accept all of the defaults, you can simply add the
`--no-prompt` option to your request.
-+
-*Example*: `bin/solr start -e cloud --no-prompt`
-
`-p <port>`::
+
[%autowidth,frame=none]
@@ -277,6 +242,56 @@ To emphasize how the default settings work take a moment
to understand that the
`bin/solr start --host localhost -p 8983 --server-dir server --solr-home solr
-m 512m`
+`-e <name>` or `--example <name>`::
++
+[%autowidth,frame=none]
+|===
+|Optional |Default: none
+|===
++
+Start Solr with an example configuration.
+These examples are provided to help you get started faster with Solr
generally, or just try a specific feature.
++
+The available options are:
+
+* `cloud`: SolrCloud example
+* `techproducts`: Comprehensive example illustrating many of Solr's core
capabilities
+* `schemaless`: Schema-less example (schema is inferred from data during
indexing)
+* `films`: Example of starting with _default configset and adding explicit
fields dynamically
++
+See the section <<Running with Example Configurations>> below for more details
on the example configurations.
++
+*Example*: `bin/solr start -e schemaless`
+
+`--no-prompt`::
++
+[%autowidth,frame=none]
+|===
+|Optional |Default: none
+|===
++
+Don't prompt for input; accept all defaults when running examples that accept
input.
++
+For example, when using the "cloud" example, an interactive session guides you
through several options for your SolrCloud cluster.
+If you want to accept all of the defaults, you can simply add the
`--no-prompt` option to your request.
++
+*Example*: `bin/solr start -e cloud --no-prompt`
+
+`--prompt-inputs <values>`::
++
+[%autowidth,frame=none]
+|===
+|Optional |Default: none
+|===
++
+Don't prompt for input; instead supply ordered answers in comma delimited
format when running examples that accept input.
++
+For example, when using the "cloud" example, you can answer the prompts
non-interactively to start a three node cluster on specific ports:
++
+*Example*: `bin/solr start -e cloud --prompt-inputs
3,9000,9001,9002,"mycollection",2,2,_default`
+
+On Windows please wrap the prompts value in double quotes to preserve the
comma delimited format.
+
It is not necessary to define all of the options when starting if the defaults
are fine for your needs.
==== Setting Java System Properties
@@ -676,7 +691,7 @@ This defaults to the same name as the collection or core.
+
*Example*: `bin/solr create -n basic`
-`-sh <shards>` or `-shards <shards>`::
+`-sh <shards>` or `--shards <shards>`::
+
[%autowidth,frame=none]
|===
@@ -937,7 +952,7 @@ Either `--credentials` or `--prompt` *must* be specified.
When `true`, this blocks out access to unauthenticated users from accessing
Solr.
When `false`, unauthenticated users will still be able to access Solr, but
only for operations not explicitly requiring a user role in the Authorization
plugin configuration.
-`--solrIncludeFile <includeFilePath>`::
+`--solr-include-file <includeFilePath>`::
+
[%autowidth,frame=none]
|===