You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ep...@apache.org on 2023/05/09 21:03:14 UTC

[solr] branch branch_9x updated: SOLR-16760: bin/solr package support the -h and -help commands like other tools (#1600)

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

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


The following commit(s) were added to refs/heads/branch_9x by this push:
     new b72f089ca01 SOLR-16760: bin/solr package support the -h and -help commands like other tools (#1600)
b72f089ca01 is described below

commit b72f089ca01aaeaa8b5197bb9b2073c3ffb996d3
Author: Eric Pugh <ep...@opensourceconnections.com>
AuthorDate: Tue May 9 17:02:21 2023 -0400

    SOLR-16760: bin/solr package support the -h and -help commands like other tools (#1600)
---
 solr/CHANGES.txt                                   |   2 +
 solr/bin/solr                                      |  32 +-
 .../src/java/org/apache/solr/cli/PackageTool.java  | 355 ++++++++++-----------
 solr/packaging/test/test_packages.bats             |  48 +++
 4 files changed, 251 insertions(+), 186 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index fc2644f159e..4b826c1b381 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -126,6 +126,8 @@ Bug Fixes
 
 * SOLR-16789: Fixed Admin UI dashboard "Security" panel to show the right information regarding authentication (Tomás Fernández Löbbe)
 
+* SOLR-16760: bin/solr package tool supports -h and -help command like other tools.  (Eric Pugh)
+
 Dependency Upgrades
 ---------------------
 * PR#1494: Upgrade forbiddenapis to 3.5 (Uwe Schindler)
diff --git a/solr/bin/solr b/solr/bin/solr
index fe91078f485..dd5b175ce1d 100644
--- a/solr/bin/solr
+++ b/solr/bin/solr
@@ -663,6 +663,10 @@ function print_usage() {
     echo ""
     echo "  -V                                     Enable more verbose output."
     echo ""
+  elif [ "$CMD" == "package" ]; then
+    echo ""
+    run_tool package -solrUrl "http://fake.to.allow.help.to.run" "help"
+
   fi
 } # end print_usage
 
@@ -746,7 +750,6 @@ function run_tool() {
 
 # get status about any Solr nodes running on this host
 function get_status() {
-  CODE=4
   # first, see if Solr is running
   numSolrs=$(find "$SOLR_PID_DIR" -name "solr-*.pid" -type f | wc -l | tr -d ' ')
   if [ "$numSolrs" != "0" ]; then
@@ -758,11 +761,9 @@ function get_status() {
         if [ "$port" != "" ]; then
           echo -e "\nSolr process $ID running on port $port"
           run_tool status -solr "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$port/solr"
-          CODE=$?
           echo ""
         else
           echo -e "\nSolr process $ID from $PIDF not found."
-          CODE=1
         fi
     done < <(find "$SOLR_PID_DIR" -name "solr-*.pid" -type f)
   else
@@ -778,17 +779,14 @@ function get_status() {
             echo ""
             echo "Solr process $ID running on port $port"
             run_tool status -solr "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$port/solr"
-            CODE=$?
             echo ""
           fi
       done
     else
       echo -e "\nNo Solr nodes are running.\n"
-      CODE=3
     fi
   fi
 
-  return $CODE
 } # end get_status
 
 function run_package() {
@@ -1408,7 +1406,7 @@ if [[ "$SCRIPT_CMD" == "zk" ]]; then
       print_short_zk_usage "<source> and <destination> must be specified when using either the 'mv' or 'cp' commands."
     fi
     if [[ "$ZK_OP" == "cp" && "${ZK_SRC:0:3}" != "zk:" && "${ZK_DST:0:3}" != "zk:" ]]; then
-      print_short_zk_usage "One of the source or desintation paths must be prefixed by 'zk:' for the 'cp' command."
+      print_short_zk_usage "One of the source or destination paths must be prefixed by 'zk:' for the 'cp' command."
     fi
   fi
 
@@ -1465,6 +1463,24 @@ if [[ "$SCRIPT_CMD" == "export" ]]; then
 fi
 
 if [[ "$SCRIPT_CMD" == "package" ]]; then
+  if [ $# -gt 0 ]; then
+    while true; do
+      case "$1" in
+          -help|-h)
+              print_usage "$SCRIPT_CMD"
+              exit 0
+          ;;
+          --)
+              shift
+              break
+          ;;
+          *)
+              break # out-of-args, stop looping
+
+          ;;
+      esac
+    done
+  fi
   run_package "$@"
   exit $?
 fi
@@ -1652,7 +1668,7 @@ if [[ "${SOLR_ULIMIT_CHECKS:-}" != "false" ]]; then
       echo "     max processes:   $SOLR_RECOMMENDED_MAX_PROCESSES "
       echo "     open files:      $SOLR_RECOMMENDED_OPEN_FILES"
       echo "     virtual memory:  unlimited"
-      echo "     max memorh size: unlimited"
+      echo "     max memory size: unlimited"
     fi
   fi
 fi
diff --git a/solr/core/src/java/org/apache/solr/cli/PackageTool.java b/solr/core/src/java/org/apache/solr/cli/PackageTool.java
index 0450bf96c13..c0e0c08e660 100644
--- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java
@@ -77,6 +77,13 @@ public class PackageTool extends ToolBase {
               + "don't print stack traces, hence special treatment is needed here.")
   public void runImpl(CommandLine cli) throws Exception {
     try {
+      String cmd = cli.getArgList().size() == 0 ? "help" : cli.getArgs()[0];
+
+      if (cmd.equalsIgnoreCase("help")) {
+        printHelp();
+        return;
+      }
+
       solrUrl = cli.getOptionValues("solrUrl")[cli.getOptionValues("solrUrl").length - 1];
       solrBaseUrl = solrUrl.replaceAll("/solr$", ""); // strip out ending "/solr"
       log.info("Solr url:{}, solr base url: {}", solrUrl, solrBaseUrl);
@@ -86,204 +93,153 @@ public class PackageTool extends ToolBase {
       }
 
       log.info("ZK: {}", zkHost);
-      String cmd = cli.getArgList().size() == 0 ? "help" : cli.getArgs()[0];
 
       try (SolrClient solrClient = new Http2SolrClient.Builder(solrBaseUrl).build()) {
-        if (cmd != null) {
-          packageManager = new PackageManager(solrClient, solrBaseUrl, zkHost);
-          try {
-            repositoryManager = new RepositoryManager(solrClient, packageManager);
+        packageManager = new PackageManager(solrClient, solrBaseUrl, zkHost);
+        try {
+          repositoryManager = new RepositoryManager(solrClient, packageManager);
 
-            switch (cmd) {
-              case "add-repo":
-                String repoName = cli.getArgs()[1];
-                String repoUrl = cli.getArgs()[2];
-                repositoryManager.addRepository(repoName, repoUrl);
-                PackageUtils.printGreen("Added repository: " + repoName);
-                break;
-              case "add-key":
-                String keyFilename = cli.getArgs()[1];
-                Path path = Path.of(keyFilename);
-                repositoryManager.addKey(Files.readAllBytes(path), path.getFileName().toString());
-                break;
-              case "list-installed":
-                PackageUtils.printGreen("Installed packages:\n-----");
-                for (SolrPackageInstance pkg : packageManager.fetchInstalledPackageInstances()) {
-                  PackageUtils.printGreen(pkg);
+          switch (cmd) {
+            case "add-repo":
+              String repoName = cli.getArgs()[1];
+              String repoUrl = cli.getArgs()[2];
+              repositoryManager.addRepository(repoName, repoUrl);
+              PackageUtils.printGreen("Added repository: " + repoName);
+              break;
+            case "add-key":
+              String keyFilename = cli.getArgs()[1];
+              Path path = Path.of(keyFilename);
+              repositoryManager.addKey(Files.readAllBytes(path), path.getFileName().toString());
+              break;
+            case "list-installed":
+              PackageUtils.printGreen("Installed packages:\n-----");
+              for (SolrPackageInstance pkg : packageManager.fetchInstalledPackageInstances()) {
+                PackageUtils.printGreen(pkg);
+              }
+              break;
+            case "list-available":
+              PackageUtils.printGreen("Available packages:\n-----");
+              for (SolrPackage pkg : repositoryManager.getPackages()) {
+                PackageUtils.printGreen(pkg.name + " \t\t" + pkg.description);
+                for (SolrPackageRelease version : pkg.versions) {
+                  PackageUtils.printGreen("\tVersion: " + version.version);
                 }
-                break;
-              case "list-available":
-                PackageUtils.printGreen("Available packages:\n-----");
-                for (SolrPackage pkg : repositoryManager.getPackages()) {
-                  PackageUtils.printGreen(pkg.name + " \t\t" + pkg.description);
-                  for (SolrPackageRelease version : pkg.versions) {
-                    PackageUtils.printGreen("\tVersion: " + version.version);
-                  }
+              }
+              break;
+            case "list-deployed":
+              if (cli.hasOption('c')) {
+                String collection = cli.getArgs()[1];
+                Map<String, SolrPackageInstance> packages =
+                    packageManager.getPackagesDeployed(collection);
+                PackageUtils.printGreen("Packages deployed on " + collection + ":");
+                for (String packageName : packages.keySet()) {
+                  PackageUtils.printGreen("\t" + packages.get(packageName));
                 }
-                break;
-              case "list-deployed":
-                if (cli.hasOption('c')) {
-                  String collection = cli.getArgs()[1];
-                  Map<String, SolrPackageInstance> packages =
-                      packageManager.getPackagesDeployed(collection);
-                  PackageUtils.printGreen("Packages deployed on " + collection + ":");
-                  for (String packageName : packages.keySet()) {
-                    PackageUtils.printGreen("\t" + packages.get(packageName));
-                  }
-                } else {
-                  String packageName = cli.getArgs()[1];
-                  Map<String, String> deployedCollections =
-                      packageManager.getDeployedCollections(packageName);
-                  if (deployedCollections.isEmpty() == false) {
+              } else {
+                String packageName = cli.getArgs()[1];
+                Map<String, String> deployedCollections =
+                    packageManager.getDeployedCollections(packageName);
+                if (!deployedCollections.isEmpty()) {
+                  PackageUtils.printGreen(
+                      "Collections on which package " + packageName + " was deployed:");
+                  for (String collection : deployedCollections.keySet()) {
                     PackageUtils.printGreen(
-                        "Collections on which package " + packageName + " was deployed:");
-                    for (String collection : deployedCollections.keySet()) {
-                      PackageUtils.printGreen(
-                          "\t"
-                              + collection
-                              + "("
-                              + packageName
-                              + ":"
-                              + deployedCollections.get(collection)
-                              + ")");
-                    }
-                  } else {
-                    PackageUtils.printGreen(
-                        "Package " + packageName + " not deployed on any collection.");
+                        "\t"
+                            + collection
+                            + "("
+                            + packageName
+                            + ":"
+                            + deployedCollections.get(collection)
+                            + ")");
                   }
+                } else {
+                  PackageUtils.printGreen(
+                      "Package " + packageName + " not deployed on any collection.");
+                }
+              }
+              break;
+            case "install":
+              {
+                Pair<String, String> parsedVersion = parsePackageVersion(cli.getArgList().get(1));
+                String packageName = parsedVersion.first();
+                String version = parsedVersion.second();
+                boolean success = repositoryManager.install(packageName, version);
+                if (success) {
+                  PackageUtils.printGreen(packageName + " installed.");
+                } else {
+                  PackageUtils.printRed(packageName + " installation failed.");
                 }
                 break;
-              case "install":
-                {
-                  Pair<String, String> parsedVersion =
-                      parsePackageVersion(cli.getArgList().get(1).toString());
+              }
+            case "deploy":
+              {
+                if (cli.hasOption("cluster") || cli.hasOption("collections")) {
+                  Pair<String, String> parsedVersion = parsePackageVersion(cli.getArgList().get(1));
                   String packageName = parsedVersion.first();
                   String version = parsedVersion.second();
-                  boolean success = repositoryManager.install(packageName, version);
-                  if (success) {
-                    PackageUtils.printGreen(packageName + " installed.");
-                  } else {
-                    PackageUtils.printRed(packageName + " installation failed.");
-                  }
-                  break;
-                }
-              case "deploy":
-                {
-                  if (cli.hasOption("cluster") || cli.hasOption("collections")) {
-                    Pair<String, String> parsedVersion =
-                        parsePackageVersion(cli.getArgList().get(1).toString());
-                    String packageName = parsedVersion.first();
-                    String version = parsedVersion.second();
-                    boolean noprompt = cli.hasOption('y');
-                    boolean isUpdate = cli.hasOption("update") || cli.hasOption('u');
-                    String collections[] =
-                        cli.hasOption("collections")
-                            ? PackageUtils.validateCollections(
-                                cli.getOptionValue("collections").split(","))
-                            : new String[] {};
-                    packageManager.deploy(
-                        packageName,
-                        version,
-                        collections,
-                        cli.hasOption("cluster"),
-                        cli.getOptionValues("param"),
-                        isUpdate,
-                        noprompt);
-                  } else {
-                    PackageUtils.printRed(
-                        "Either specify -cluster to deploy cluster level plugins or -collections <list-of-collections> to deploy collection level plugins");
-                  }
-                  break;
-                }
-              case "undeploy":
-                {
-                  if (cli.hasOption("cluster") || cli.hasOption("collections")) {
-                    Pair<String, String> parsedVersion =
-                        parsePackageVersion(cli.getArgList().get(1).toString());
-                    if (parsedVersion.second() != null) {
-                      throw new SolrException(
-                          ErrorCode.BAD_REQUEST,
-                          "Only package name expected, without a version. Actual: "
-                              + cli.getArgList().get(1));
-                    }
-                    String packageName = parsedVersion.first();
-                    String collections[] =
-                        cli.hasOption("collections")
-                            ? PackageUtils.validateCollections(
-                                cli.getOptionValue("collections").split(","))
-                            : new String[] {};
-                    packageManager.undeploy(packageName, collections, cli.hasOption("cluster"));
-                  } else {
-                    PackageUtils.printRed(
-                        "Either specify -cluster to undeploy cluster level plugins or -collections <list-of-collections> to undeploy collection level plugins");
-                  }
-                  break;
+                  boolean noprompt = cli.hasOption('y');
+                  boolean isUpdate = cli.hasOption("update") || cli.hasOption('u');
+                  String[] collections =
+                      cli.hasOption("collections")
+                          ? PackageUtils.validateCollections(
+                              cli.getOptionValue("collections").split(","))
+                          : new String[] {};
+                  packageManager.deploy(
+                      packageName,
+                      version,
+                      collections,
+                      cli.hasOption("cluster"),
+                      cli.getOptionValues("param"),
+                      isUpdate,
+                      noprompt);
+                } else {
+                  PackageUtils.printRed(
+                      "Either specify -cluster to deploy cluster level plugins or -collections <list-of-collections> to deploy collection level plugins");
                 }
-              case "uninstall":
-                {
-                  Pair<String, String> parsedVersion =
-                      parsePackageVersion(cli.getArgList().get(1).toString());
-                  if (parsedVersion.second() == null) {
+                break;
+              }
+            case "undeploy":
+              {
+                if (cli.hasOption("cluster") || cli.hasOption("collections")) {
+                  Pair<String, String> parsedVersion = parsePackageVersion(cli.getArgList().get(1));
+                  if (parsedVersion.second() != null) {
                     throw new SolrException(
                         ErrorCode.BAD_REQUEST,
-                        "Package name and version are both required. Actual: "
+                        "Only package name expected, without a version. Actual: "
                             + cli.getArgList().get(1));
                   }
                   String packageName = parsedVersion.first();
-                  String version = parsedVersion.second();
-                  packageManager.uninstall(packageName, version);
-                  break;
+                  String[] collections =
+                      cli.hasOption("collections")
+                          ? PackageUtils.validateCollections(
+                              cli.getOptionValue("collections").split(","))
+                          : new String[] {};
+                  packageManager.undeploy(packageName, collections, cli.hasOption("cluster"));
+                } else {
+                  PackageUtils.printRed(
+                      "Either specify -cluster to undeploy cluster level plugins or -collections <list-of-collections> to undeploy collection level plugins");
                 }
-              case "help":
-              case "usage":
-                print("Package Manager\n---------------");
-                printGreen("./solr package add-repo <repository-name> <repository-url>");
-                print("Add a repository to Solr.");
-                print("");
-                printGreen("./solr package add-key <file-containing-trusted-key>");
-                print("Add a trusted key to Solr.");
-                print("");
-                printGreen("./solr package install <package-name>[:<version>] ");
-                print(
-                    "Install a package into Solr. This copies over the artifacts from the repository into Solr's internal package store and sets up classloader for this package to be used.");
-                print("");
-                printGreen(
-                    "./solr package deploy <package-name>[:<version>] [-y] [--update] -collections <comma-separated-collections> [-p <param1>=<val1> -p <param2>=<val2> ...] ");
-                print(
-                    "Bootstraps a previously installed package into the specified collections. It the package accepts parameters for its setup commands, they can be specified (as per package documentation).");
-                print("");
-                printGreen("./solr package list-installed");
-                print("Print a list of packages installed in Solr.");
-                print("");
-                printGreen("./solr package list-available");
-                print("Print a list of packages available in the repositories.");
-                print("");
-                printGreen("./solr package list-deployed -c <collection>");
-                print("Print a list of packages deployed on a given collection.");
-                print("");
-                printGreen("./solr package list-deployed <package-name>");
-                print("Print a list of collections on which a given package has been deployed.");
-                print("");
-                printGreen(
-                    "./solr package undeploy <package-name> -collections <comma-separated-collections>");
-                print("Undeploys a package from specified collection(s)");
-                print("");
-                printGreen("./solr package uninstall <package-name>:<version>");
-                print(
-                    "Uninstall an unused package with specified version from Solr. Both package name and version are required.");
-                print("\n");
-                print(
-                    "Note: (a) Please add '-solrUrl http://host:port' parameter if needed (usually on Windows).");
-                print(
-                    "      (b) Please make sure that all Solr nodes are started with '-Denable.packages=true' parameter.");
-                print("\n");
                 break;
-              default:
-                throw new RuntimeException("Unrecognized command: " + cmd);
-            }
-          } finally {
-            packageManager.close();
+              }
+            case "uninstall":
+              {
+                Pair<String, String> parsedVersion = parsePackageVersion(cli.getArgList().get(1));
+                if (parsedVersion.second() == null) {
+                  throw new SolrException(
+                      ErrorCode.BAD_REQUEST,
+                      "Package name and version are both required. Actual: "
+                          + cli.getArgList().get(1));
+                }
+                String packageName = parsedVersion.first();
+                String version = parsedVersion.second();
+                packageManager.uninstall(packageName, version);
+                break;
+              }
+            default:
+              throw new RuntimeException("Unrecognized command: " + cmd);
           }
+        } finally {
+          packageManager.close();
         }
       }
       log.info("Finished: {}", cmd);
@@ -296,6 +252,49 @@ public class PackageTool extends ToolBase {
     }
   }
 
+  private void printHelp() {
+    print("Package Manager\n---------------");
+    printGreen("./solr package add-repo <repository-name> <repository-url>");
+    print("Add a repository to Solr.");
+    print("");
+    printGreen("./solr package add-key <file-containing-trusted-key>");
+    print("Add a trusted key to Solr.");
+    print("");
+    printGreen("./solr package install <package-name>[:<version>] ");
+    print(
+        "Install a package into Solr. This copies over the artifacts from the repository into Solr's internal package store and sets up classloader for this package to be used.");
+    print("");
+    printGreen(
+        "./solr package deploy <package-name>[:<version>] [-y] [--update] -collections <comma-separated-collections> [-p <param1>=<val1> -p <param2>=<val2> ...] ");
+    print(
+        "Bootstraps a previously installed package into the specified collections. It the package accepts parameters for its setup commands, they can be specified (as per package documentation).");
+    print("");
+    printGreen("./solr package list-installed");
+    print("Print a list of packages installed in Solr.");
+    print("");
+    printGreen("./solr package list-available");
+    print("Print a list of packages available in the repositories.");
+    print("");
+    printGreen("./solr package list-deployed -c <collection>");
+    print("Print a list of packages deployed on a given collection.");
+    print("");
+    printGreen("./solr package list-deployed <package-name>");
+    print("Print a list of collections on which a given package has been deployed.");
+    print("");
+    printGreen("./solr package undeploy <package-name> -collections <comma-separated-collections>");
+    print("Undeploy a package from specified collection(s)");
+    print("");
+    printGreen("./solr package uninstall <package-name>:<version>");
+    print(
+        "Uninstall an unused package with specified version from Solr. Both package name and version are required.");
+    print("\n");
+    print(
+        "Note: (a) Please add '-solrUrl http://host:port' parameter if needed (usually on Windows).");
+    print(
+        "      (b) Please make sure that all Solr nodes are started with '-Denable.packages=true' parameter.");
+    print("\n");
+  }
+
   /**
    * Parses package name and version in the format "name:version" or "name"
    *
diff --git a/solr/packaging/test/test_packages.bats b/solr/packaging/test/test_packages.bats
new file mode 100644
index 00000000000..dc2ef88c618
--- /dev/null
+++ b/solr/packaging/test/test_packages.bats
@@ -0,0 +1,48 @@
+#!/usr/bin/env bats
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load bats_helper
+
+setup() {
+  common_clean_setup
+}
+
+teardown() {
+  # save a snapshot of SOLR_HOME for failed tests
+  save_home_on_failure
+
+  solr stop -all >/dev/null 2>&1
+}
+
+@test "package detects no running solr" {
+  # not sure this is actually a good thing..  we may not want this..
+  run solr package
+  assert_output --partial "No Solr nodes are running."
+}
+
+@test "lifecycle of package" {
+  run solr start -c -Denable.packages=true
+
+  run solr package
+  refute_output --partial "No Solr nodes are running."
+
+  run solr package -help
+  assert_output --partial "Add a repository to Solr"
+
+  run solr package list-available
+  assert_output --partial "Available packages:"
+}