This is an automated email from the ASF dual-hosted git repository.

janhoy pushed a commit to branch branch_10_0
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_10_0 by this push:
     new 62505abefe0 SOLR-17690 Make solr zk tools read ZK_HOST environment 
(#3240)
62505abefe0 is described below

commit 62505abefe0a020be74a9adfbf921da8aa3834ff
Author: Jan Høydahl <[email protected]>
AuthorDate: Tue Oct 28 10:22:18 2025 +0100

    SOLR-17690 Make solr zk tools read ZK_HOST environment (#3240)
    
    (cherry picked from commit d229ee4f2d1dc46898c48d36eff18e5706cd612a)
---
 .../feature/SOLR-17690-zkToolZKHostFromEnv.yml     | 10 ++++++
 .../src/java/org/apache/solr/cli/CLIUtils.java     | 31 ++++++++++++++---
 .../java/org/apache/solr/cli/RunExampleTool.java   |  6 ++--
 .../org/apache/solr/cli/ZkSubcommandsTest.java     |  4 +--
 solr/packaging/test/test_zk.bats                   | 26 +++++++++++++--
 .../pages/solr-control-script-reference.adoc       | 39 +++++++++++-----------
 .../pages/zookeeper-utilities.adoc                 | 11 ++++++
 7 files changed, 97 insertions(+), 30 deletions(-)

diff --git a/changelog/unreleased/feature/SOLR-17690-zkToolZKHostFromEnv.yml 
b/changelog/unreleased/feature/SOLR-17690-zkToolZKHostFromEnv.yml
new file mode 100644
index 00000000000..2231fc3ea75
--- /dev/null
+++ b/changelog/unreleased/feature/SOLR-17690-zkToolZKHostFromEnv.yml
@@ -0,0 +1,10 @@
+# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
+title: Make solr zk tools read ZK_HOST environment
+type: changed # added, changed, fixed, deprecated, removed, dependency_update, 
security, other
+authors:
+  - name: Jan Høydahl
+    nick: janhoy
+    url: https://home.apache.org/phonebook.html?uid=janhoy
+links:
+  - name: SOLR-17690
+    url: https://issues.apache.org/jira/browse/SOLR-17690
diff --git a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java 
b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java
index c04e02fc160..340d0fb13a6 100644
--- a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java
+++ b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java
@@ -35,6 +35,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
 import org.apache.commons.exec.OS;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrRequest;
@@ -190,11 +191,11 @@ public final class CLIUtils {
     String solrUrl = cli.getOptionValue(CommonCLIOptions.SOLR_URL_OPTION);
 
     if (solrUrl == null) {
-      String zkHost = cli.getOptionValue(CommonCLIOptions.ZK_HOST_OPTION);
+      String zkHost = getCliOptionOrPropValue(cli, 
CommonCLIOptions.ZK_HOST_OPTION, "zkHost", null);
       if (zkHost == null) {
         solrUrl = getDefaultSolrUrl();
         CLIO.err(
-            "Neither --zk-host or --solr-url parameters provided so assuming 
solr url is "
+            "Neither --zk-host or --solr-url parameters, nor ZK_HOST env var 
provided, so assuming solr url is "
                 + solrUrl
                 + ".");
       } else {
@@ -216,12 +217,32 @@ public final class CLIUtils {
   }
 
   /**
-   * Get the ZooKeeper connection string from either the zk-host command-line 
option or by looking
-   * it up from a running Solr instance based on the solr-url option.
+   * Get the value of the specified CLI option with fallback to system 
property and default value.
+   *
+   * @param cli the command line
+   * @param option the commons cli {@link Option}
+   * @param sysprop the system property to fall back to
+   * @param defaultValue the default value. Use null if no default value is 
desired
+   * @return the value of the option or system property or the default value
+   */
+  public static String getCliOptionOrPropValue(
+      CommandLine cli, Option option, String sysprop, String defaultValue) {
+    String value = cli.getOptionValue(option);
+    if (value == null) {
+      value = EnvUtils.getProperty(sysprop, defaultValue);
+    }
+    return value;
+  }
+
+  /**
+   * Get the ZooKeeper connection string from either the zk-host command-line 
option or if not
+   * configured, from the 'zkHost' system property aka the 'ZK_HOST' 
environment variable. If
+   * neither is configured, we attempt looking it up from a running Solr 
instance based on the
+   * solr-url option.
    */
   public static String getZkHost(CommandLine cli) throws Exception {
 
-    String zkHost = cli.getOptionValue(CommonCLIOptions.ZK_HOST_OPTION);
+    String zkHost = getCliOptionOrPropValue(cli, 
CommonCLIOptions.ZK_HOST_OPTION, "zkHost", null);
     if (zkHost != null && !zkHost.isBlank()) {
       return zkHost;
     }
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 5be8b5af4e0..1c6deb6ffe9 100644
--- a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
@@ -302,7 +302,8 @@ public class RunExampleTool extends ToolBase {
         "techproducts".equals(exampleName) ? "sample_techproducts_configs" : 
"_default";
 
     boolean isCloudMode = !cli.hasOption(USER_MANAGED_OPTION);
-    String zkHost = cli.getOptionValue(CommonCLIOptions.ZK_HOST_OPTION);
+    String zkHost =
+        CLIUtils.getCliOptionOrPropValue(cli, CommonCLIOptions.ZK_HOST_OPTION, 
"zkHost", null);
     int port =
         Integer.parseInt(
             cli.getOptionValue(PORT_OPTION, 
System.getenv().getOrDefault("SOLR_PORT", "8983")));
@@ -581,7 +582,8 @@ public class RunExampleTool extends ToolBase {
     }
 
     // deal with extra args passed to the script to run the example
-    String zkHost = cli.getOptionValue(CommonCLIOptions.ZK_HOST_OPTION);
+    String zkHost =
+        CLIUtils.getCliOptionOrPropValue(cli, CommonCLIOptions.ZK_HOST_OPTION, 
"zkHost", null);
 
     // start the first node (most likely with embedded ZK)
     Map<String, Object> nodeStatus =
diff --git a/solr/core/src/test/org/apache/solr/cli/ZkSubcommandsTest.java 
b/solr/core/src/test/org/apache/solr/cli/ZkSubcommandsTest.java
index 6fce5e80127..2dad25d6719 100644
--- a/solr/core/src/test/org/apache/solr/cli/ZkSubcommandsTest.java
+++ b/solr/core/src/test/org/apache/solr/cli/ZkSubcommandsTest.java
@@ -501,8 +501,8 @@ public class ZkSubcommandsTest extends SolrTestCaseJ4 {
     Path file =
         tmpDir.resolve("solrtest-getfile-" + this.getClass().getName() + "-" + 
System.nanoTime());
 
-    String[] args =
-        new String[] {"cp", "-z", zkServer.getZkAddress(), "zk:" + getNode, 
file.toString()};
+    // Not setting --zk-host, will fall back to sysProp 'zkHost'
+    String[] args = new String[] {"cp", "zk:" + getNode, file.toString()};
 
     assertEquals(0, CLITestHelper.runTool(args, ZkCpTool.class));
     assertArrayEquals(data, Files.readAllBytes(file));
diff --git a/solr/packaging/test/test_zk.bats b/solr/packaging/test/test_zk.bats
index d516637cfb8..fc31f691bef 100644
--- a/solr/packaging/test/test_zk.bats
+++ b/solr/packaging/test/test_zk.bats
@@ -68,7 +68,7 @@ teardown() {
   sleep 1
   run solr zk ls / --solr-url http://localhost:${SOLR_PORT}
   assert_output --partial "aliases.json"
- 
+
   run solr zk ls / -s http://localhost:${SOLR_PORT}
   assert_output --partial "aliases.json"
 
@@ -160,10 +160,32 @@ teardown() {
   run solr zk cp afile.txt zk:/afile.txt -z localhost:${ZK_PORT} --verbose 
--solr-home ${SOLR_TIP}/server/solr
   assert_output --partial "Using SolrHome: ${SOLR_TIP}/server/solr"
   refute_output --partial 'Failed to load solr.xml from ZK or SolrHome'
-  
+
   # The -DminStateByteLenForCompression variable substitution on solr start is 
not seen
   # by the ZkCpTool.java, so therefore we do not have compression unless 
solr.xml is directly edited.
   #assert_output --partial 'Compression of state.json has been enabled'
 
   rm afile.txt
 }
+
+@test "env var ZK_HOST is honored" {
+  sleep 1
+
+  # Need to unset SOLR_PORT to avoid the tool being smart and look at SOLR_PORT
+  export SOLR_PORT_KEEP=$SOLR_PORT
+  unset SOLR_PORT
+
+  # First test a command that will fail (no ZK_HOST set, no SOLR_PORT)
+  run solr zk ls / --recursive
+  assert_output --partial "assuming solr url is http://localhost:8983";
+  refute_output --partial "aliases.json"
+
+  # Then set the ZK_HOST variable and test again
+  export ZK_HOST=localhost:${ZK_PORT}
+  run solr zk ls / --recursive
+  assert_output --partial "aliases.json"
+
+  # Restore SOLR_PORT
+  export SOLR_PORT=$SOLR_PORT_KEEP
+  unset ZK_HOST
+}
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 f8d50fabafb..4868f5e2ef7 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
@@ -557,13 +557,10 @@ Base Solr URL, which can be used in SolrCloud mode to 
determine the ZooKeeper co
 +
 [%autowidth,frame=none]
 |===
-|Optional |Default: `localhost:9983`
+|Optional |Default: `localhost:9983` if env var `ZK_HOST` is not set.
 |===
 +
 ZooKeeper connection string.
-If you are running Solr on a port other than 8983, you will have to specify 
the ZooKeeper connection string.
-By default, this will be the Solr port + 1000.
-This parameter is unnecessary if `ZK_HOST` is defined in `solr.in.sh` or 
`solr.in.cmd`.
 +
 *Example*: `bin/solr healthcheck -z localhost:2181`
 
@@ -1144,6 +1141,17 @@ Usage: solr zk upconfig|downconfig -d <confdir> -n 
<configName> [-z zkHost] [-s
 NOTE: Solr should have been started at least once before issuing these 
commands to initialize ZooKeeper with the znodes Solr expects.
 Once ZooKeeper is initialized, Solr doesn't need to be running on any node to 
use these commands.
 
+=== ZooKeeper Connection String
+
+All `bin/solr zk` sub-commands require a ZooKeeper connection string to 
function. You can provide this in three ways, in order of precedence:
+
+1. Explicitly pass the `-z` or `--zk-host` option: `bin/solr zk <command> -z 
<zkHost>`
+2. Set the `ZK_HOST` environment variable: `export ZK_HOST=<zkHost>`
+3. Define `ZK_HOST` in `solr.in.sh` (or `solr.in.cmd` on Windows)
+4. If none are provided, the tools will default to `localhost:2181`
+
+This means if you have `ZK_HOST` configured in your environment, you do not 
need to pass the `-z` option to every command.
+
 === Upload a Configuration Set
 
 Use the `zk upconfig` command to upload one of the pre-configured 
configuration sets or a customized configuration set to ZooKeeper.
@@ -1191,11 +1199,10 @@ An absolute path may be supplied instead.
 +
 [%autowidth,frame=none]
 |===
-s|Required |Default: none
+|Optional |Default: `localhost:2181` if `ZK_HOST` env var not set
 |===
 +
 The ZooKeeper connection string.
-Is not required if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
 +
 *Example*: `-z 123.321.23.43:2181`
 
@@ -1263,11 +1270,10 @@ In either case, _pre-existing configurations at the 
destination will be overwrit
 +
 [%autowidth,frame=none]
 |===
-s|Required |Default: none
+|Optional |Default: `localhost:2181` if `ZK_HOST` env var not set
 |===
 +
 The ZooKeeper connection string.
-Unnecessary if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
 +
 *Example*: `-z 123.321.23.43:2181`
 
@@ -1347,11 +1353,10 @@ If `<dest>` ends in a slash character it names a 
directory.
 +
 [%autowidth,frame=none]
 |===
-s|Required |Default: none
+|Optional |Default: `localhost:2181` if `ZK_HOST` env var not set
 |===
 +
 The ZooKeeper connection string.
-Optional if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
 +
 *Example*: `-z 123.321.23.43:2181`
 
@@ -1430,11 +1435,10 @@ The path is assumed to be a ZooKeeper node, no `zk:` 
prefix is necessary.
 +
 [%autowidth,frame=none]
 |===
-s|Required |Default: none
+|Optional |Default: `localhost:2181` if `ZK_HOST` env var not set
 |===
 +
 The ZooKeeper connection string.
-Optional if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
 +
 *Example*: `-z 123.321.23.43:2181`
 
@@ -1488,11 +1492,10 @@ The `zk:` prefix is assumed.
 +
 [%autowidth,frame=none]
 |===
-s|Required |Default: none
+|Optional |Default: `localhost:2181` if `ZK_HOST` env var not set
 |===
 +
 The ZooKeeper connection string.
-Unnecessary if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
 +
 *Example*: `-z 123.321.23.43:2181`
 
@@ -1543,11 +1546,10 @@ The path on ZooKeeper to list.
 +
 [%autowidth,frame=none]
 |===
-s|Required |Default: none
+|Optional |Default: `localhost:2181` if `ZK_HOST` env var not set
 |===
 +
 The ZooKeeper connection string.
-Optional if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
 +
 *Example*: `-z 123.321.23.43:2181`
 
@@ -1592,11 +1594,10 @@ A leading slash is assumed if not present.
 +
 [%autowidth,frame=none]
 |===
-s|Required |Default: none
+|Optional |Default: `localhost:2181` if `ZK_HOST` env var not set
 |===
 +
 The ZooKeeper connection string.
-Optional if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
 +
 *Example*: `-z 123.321.23.43:2181`
 
@@ -1745,7 +1746,7 @@ bin/solr export --solr-url http://localhost:8983 -c 
gettingstarted --limit -1 --
 === Importing Documents into a Collection
 
 Once you have exported documents in a file, you can use the 
xref:indexing-guide:indexing-with-update-handlers.adoc#json-formatted-index-updates[/update
 request handler] to import them to a new Solr collection.
-Notice the different endpoints used depending on the format.  
+Notice the different endpoints used depending on the format.
 
 *Example: import `json` files*
 
diff --git 
a/solr/solr-ref-guide/modules/deployment-guide/pages/zookeeper-utilities.adoc 
b/solr/solr-ref-guide/modules/deployment-guide/pages/zookeeper-utilities.adoc
index fb2a54b0478..0da801f99ec 100644
--- 
a/solr/solr-ref-guide/modules/deployment-guide/pages/zookeeper-utilities.adoc
+++ 
b/solr/solr-ref-guide/modules/deployment-guide/pages/zookeeper-utilities.adoc
@@ -28,6 +28,17 @@ The ZooKeeper specific commands are provided by the 
xref:solr-control-script-ref
 
 Use the `help` option to get a list of available ZooKeeper specific commands 
from the script itself, as in `bin/solr zk -h`.
 
+=== ZooKeeper Connection String
+
+All `bin/solr zk` sub-commands require a ZooKeeper connection string to 
function. You can provide this in three ways, in order of precedence:
+
+1. Explicitly pass the `-z` or `--zk-host` option: `bin/solr zk <command> -z 
<zkHost>`
+2. Set the `ZK_HOST` environment variable: `export ZK_HOST=<zkHost>`
+3. Define `ZK_HOST` in `solr.in.sh` (or `solr.in.cmd` on Windows)
+4. If none are provided, the tools will default to `localhost:2181`
+
+This means if you have `ZK_HOST` configured in your environment, you do not 
need to pass the `-z` option to every command.
+
 == Solr CLI Examples
 
 Below are some examples of using the `bin/solr` CLI which assume you have 
already started the SolrCloud example (`bin/solr start -e cloud --no-prompt`)

Reply via email to