From f71a9328f9fa9958ca43dae6968aaa94fb478f3b Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 15 Aug 2026 13:45:14 +0530 Subject: [PATCH 01/23] prompt done --- .../java/org/apache/solr/cli/PackageTool.java | 460 ++++++++++++------ .../src/java/org/apache/solr/cli/SolrCLI.java | 3 +- 2 files changed, 311 insertions(+), 152 deletions(-) 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 9dea8aaba9e9..a9aae6039216 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -24,6 +24,7 @@ import java.lang.invoke.MethodHandles; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; import java.util.Map; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; @@ -33,8 +34,10 @@ import org.apache.logging.log4j.core.config.Configurator; import org.apache.lucene.util.SuppressForbidden; import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; +import org.apache.solr.common.util.EnvUtils; import org.apache.solr.common.util.Pair; import org.apache.solr.packagemanager.PackageManager; import org.apache.solr.packagemanager.PackageUtils; @@ -46,6 +49,27 @@ import org.slf4j.LoggerFactory; /** Supports package command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "package", + description = "Install, deploy and manage Solr packages in SolrCloud.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0:Operation completed successfully.", + "1:Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # Add a package repository", + " bin/solr package add-repo myrepo https://my.repo.example/solr-packages", + "", + " # Install a package and deploy it to a collection", + " bin/solr package install mypkg-1.0.0", + " bin/solr package deploy mypkg-1.0.0 --collections myCollection -y", + "", + " # List packages deployed on a collection", + " bin/solr package list-deployed -c myCollection" + }) public class PackageTool extends ToolBase { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -93,6 +117,72 @@ public class PackageTool extends ToolBase { .desc("Don't prompt for input; accept all default choices, defaults to false.") .get(); + record PackageFlags( + String collections, + boolean cluster, + String[] parameters, + boolean update, + String collection, + boolean noPrompt) {} + + // --- picocli fields --- + + @picocli.CommandLine.ArgGroup(exclusive = true, multiplicity = "0..1") + private ConnectionOptions connectionOptions; + + @picocli.CommandLine.Mixin private CredentialsOptions credentialsOptions; + + @picocli.CommandLine.Parameters( + index = "0", + arity = "1", + paramLabel = "COMMAND", + description = "Package command: add-repo, add-key, list-installed, list-available, list-deployed, install, deploy, undeploy, uninstall.") + private String cmd; + + @picocli.CommandLine.Parameters( + index = "1..*", + arity = "0..*", + paramLabel = "ARGS", + description = "Command-specific arguments (package name[:version], repository name/URL, key file, etc.).") + private String[] cmdArgs; + + @picocli.CommandLine.Option( + names = {"--collections"}, + paramLabel = "COLLECTIONS", + description = "Specifies that this action should affect plugins for the given collection only, excluding cluster level plugins.") + private String collections; + + @picocli.CommandLine.Option( + names = {"--cluster"}, + description = "Specifies that this action should affect cluster level plugins only.") + private boolean cluster; + + @picocli.CommandLine.Option( + names = {"--param"}, + paramLabel = "PARAMS", + description = "List of parameters to be used with the deploy command.") + private String[] param; + + @picocli.CommandLine.Option( + names = {"--update"}, + description = "If a deployment is an update over a previous deployment.") + private boolean update; + + @picocli.CommandLine.Option( + names = {"-c", "--collection"}, + paramLabel = "COLLECTION", + description = "The collection to apply the package to.") + private String collection; + + @picocli.CommandLine.Option( + names = {"-y", "--no-prompt"}, + description = "Don't prompt for input; accept all default choices, defaults to false.") + private boolean noPrompt; + + public PackageTool() { + this(new DefaultToolRuntime()); + } + public PackageTool(ToolRuntime runtime) { super(runtime); } @@ -113,185 +203,198 @@ public String getName() { + "don't print stack traces, hence special treatment is needed here." + "Need to turn off logging, and SLF4J doesn't seem to provide for a way.") public void runImpl(CommandLine cli) throws Exception { + String solrUrl = CLIUtils.normalizeSolrUrl(cli); + String zkHost = CLIUtils.getZkHost(cli); + String credentials = cli.getOptionValue(CommonCLIOptions.CREDENTIALS_OPTION); + String command = cli.getArgs()[0]; + String[] cmdArgs = Arrays.copyOfRange(cli.getArgs(), 1, cli.getArgs().length); + PackageFlags packageFlags = new PackageFlags( + cli.getOptionValue(COLLECTIONS_OPTION), + cli.hasOption(CLUSTER_OPTION), + cli.getOptionValues(PARAM_OPTION), + cli.hasOption(UPDATE_OPTION), + cli.getOptionValue(COLLECTION_OPTION), + cli.hasOption(NO_PROMPT_OPTION)); + + executePackage(solrUrl, zkHost, credentials, command, cmdArgs, packageFlags); + } + + private void executePackage( + String solrUrl, + String zkHost, + String credentials, + String command, + String[] cmdArgs, + PackageFlags packageFlags) throws Exception { // Need a logging free, clean output going through to the user. Level oldLevel = LoggerContext.getContext(false).getRootLogger().getLevel(); Configurator.setRootLevel(Level.OFF); try { - String solrUrl = CLIUtils.normalizeSolrUrl(cli); - String zkHost = CLIUtils.getZkHost(cli); if (zkHost == null) { throw new SolrException(ErrorCode.INVALID_STATE, "Package manager runs only in SolrCloud"); } log.info("ZK: {}", zkHost); - String cmd = cli.getArgs()[0]; - - try (SolrClient solrClient = CLIUtils.getSolrClient(cli, true)) { + try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials, true)) { packageManager = new PackageManager(runtime, solrClient, solrUrl, 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); - 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": - printGreen("Installed packages:\n-----"); - for (SolrPackageInstance pkg : packageManager.fetchInstalledPackageInstances()) { - printGreen(pkg); - } - break; - case "list-available": - printGreen("Available packages:\n-----"); - for (SolrPackage pkg : repositoryManager.getPackages()) { - printGreen(pkg.name + " \t\t" + pkg.description); - for (SolrPackageRelease version : pkg.versions) { - printGreen("\tVersion: " + version.version); - } - } - break; - case "list-deployed": - if (cli.hasOption(COLLECTION_OPTION)) { - String collection = cli.getOptionValue(COLLECTION_OPTION); - Map packages = - packageManager.getPackagesDeployed(collection); - printGreen("Packages deployed on " + collection + ":"); - for (String packageName : packages.keySet()) { - printGreen("\t" + packages.get(packageName)); - } - } else { - // nuance that we use an arg here instead of requiring a --package parameter with a - // value - // in this code path - String packageName = cli.getArgs()[1]; - Map deployedCollections = - packageManager.getDeployedCollections(packageName); - if (!deployedCollections.isEmpty()) { - printGreen("Collections on which package " + packageName + " was deployed:"); - for (String collection : deployedCollections.keySet()) { - printGreen( - "\t" - + collection - + "(" - + packageName - + ":" - + deployedCollections.get(collection) - + ")"); - } - } else { - printGreen("Package " + packageName + " not deployed on any collection."); - } - } - break; - case "install": - { - Pair parsedVersion = parsePackageVersion(cli.getArgList().get(1)); - String packageName = parsedVersion.first(); - String version = parsedVersion.second(); - boolean success = repositoryManager.install(packageName, version); - if (success) { - printGreen(packageName + " installed."); - } else { - printRed(packageName + " installation failed."); - } - break; - } - case "deploy": - { - if (cli.hasOption(CLUSTER_OPTION) || cli.hasOption(COLLECTIONS_OPTION)) { - Pair parsedVersion = parsePackageVersion(cli.getArgList().get(1)); - String packageName = parsedVersion.first(); - String version = parsedVersion.second(); - boolean noPrompt = cli.hasOption(NO_PROMPT_OPTION); - boolean isUpdate = cli.hasOption(UPDATE_OPTION); - String[] collections = - cli.hasOption(COLLECTIONS_OPTION) - ? PackageUtils.validateCollections( - cli.getOptionValue(COLLECTIONS_OPTION).split(",")) - : new String[] {}; - String[] parameters = cli.getOptionValues(PARAM_OPTION); - packageManager.deploy( - packageName, - version, - collections, - cli.hasOption(CLUSTER_OPTION), - parameters, - isUpdate, - noPrompt); - } else { - printRed( - "Either specify --cluster to deploy cluster level plugins or --collections to deploy collection level plugins"); - } - break; - } - case "undeploy": - { - if (cli.hasOption(CLUSTER_OPTION) || cli.hasOption(COLLECTIONS_OPTION)) { - Pair parsedVersion = parsePackageVersion(cli.getArgList().get(1)); - 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_OPTION) - ? PackageUtils.validateCollections( - cli.getOptionValue(COLLECTIONS_OPTION).split(",")) - : new String[] {}; - packageManager.undeploy(packageName, collections, cli.hasOption(CLUSTER_OPTION)); - } else { - printRed( - "Either specify --cluster to undeploy cluster level plugins or -collections to undeploy collection level plugins"); - } - break; - } - case "uninstall": - { - Pair 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); - } + handleCommand(command, cmdArgs, packageFlags); } finally { packageManager.close(); } } log.info("Finished: {}", cmd); - } catch (Exception ex) { + } catch (Exception exception) { // We need to print this since SolrCLI drops the stack trace in favour // of brevity. Package tool should surely print the full stacktrace! - ex.printStackTrace(); - throw ex; + exception.printStackTrace(); + throw exception; } finally { // Restore the old logging level Configurator.setRootLevel(oldLevel); } } + private void handleCommand(String command, String[] cmdArgs, PackageFlags packageFlags) throws Exception { + switch (command) { + case "add-repo": + String repoName = cmdArgs[0]; + String repoUrl = cmdArgs[1]; + repositoryManager.addRepository(repoName, repoUrl); + printGreen("Added repository: " + repoName); + break; + case "add-key": + String keyFilename = cmdArgs[0]; + Path path = Path.of(keyFilename); + repositoryManager.addKey(Files.readAllBytes(path), path.getFileName().toString()); + break; + case "list-installed": + printGreen("Installed packages:\n-----"); + for (SolrPackageInstance pkg : packageManager.fetchInstalledPackageInstances()) { + printGreen(pkg); + } + break; + case "list-available": + printGreen("Available packages:\n-----"); + for (SolrPackage pkg : repositoryManager.getPackages()) { + printGreen(pkg.name + " \t\t" + pkg.description); + for (SolrPackageRelease version : pkg.versions) { + printGreen("\tVersion: " + version.version); + } + } + break; + case "list-deployed": + if (packageFlags.collection() != null) { + String collection = packageFlags.collection(); + Map packages = + packageManager.getPackagesDeployed(collection); + printGreen("Packages deployed on " + collection + ":"); + for (String packageName : packages.keySet()) { + printGreen("\t" + packages.get(packageName)); + } + } else { + // nuance that we use an arg here instead of requiring a --package parameter with a + // value + // in this code path + String packageName = cmdArgs[0]; + Map deployedCollections = + packageManager.getDeployedCollections(packageName); + if (!deployedCollections.isEmpty()) { + printGreen("Collections on which package " + packageName + " was deployed:"); + for (String collection : deployedCollections.keySet()) { + printGreen( + "\t" + + collection + + "(" + + packageName + + ":" + + deployedCollections.get(collection) + + ")"); + } + } else { + printGreen("Package " + packageName + " not deployed on any collection."); + } + } + break; + case "install": + { + Pair parsedVersion = parsePackageVersion(cmdArgs[0]); + String packageName = parsedVersion.first(); + String version = parsedVersion.second(); + boolean success = repositoryManager.install(packageName, version); + if (success) { + printGreen(packageName + " installed."); + } else { + printRed(packageName + " installation failed."); + } + break; + } + case "deploy": + { + if (packageFlags.cluster() || packageFlags.collections() != null) { + Pair parsedVersion = parsePackageVersion(cmdArgs[0]); + String packageName = parsedVersion.first(); + String version = parsedVersion.second(); + String[] collections = packageFlags.collections() != null + ? PackageUtils.validateCollections(packageFlags.collections().split(",")) + : new String[] {}; + packageManager.deploy( + packageName, + version, + collections, + packageFlags.cluster(), + packageFlags.parameters(), + packageFlags.update(), + packageFlags.noPrompt()); + } else { + printRed( + "Either specify --cluster to deploy cluster level plugins or --collections to deploy collection level plugins"); + } + break; + } + case "undeploy": + { + if (packageFlags.cluster() || packageFlags.collections() != null) { + Pair parsedVersion = parsePackageVersion(cmdArgs[0]); + if (parsedVersion.second() != null) { + throw new SolrException( + ErrorCode.BAD_REQUEST, + "Only package name expected, without a version. Actual: " + cmdArgs[0]); + } + String packageName = parsedVersion.first(); + String[] collections = packageFlags.collections() != null + ? PackageUtils.validateCollections(packageFlags.collections().split(",")) + : new String[] {}; + packageManager.undeploy(packageName, collections, packageFlags.cluster()); + } else { + printRed( + "Either specify --cluster to undeploy cluster level plugins or -collections to undeploy collection level plugins"); + } + break; + } + case "uninstall": + { + Pair parsedVersion = parsePackageVersion(cmdArgs[0]); + if (parsedVersion.second() == null) { + throw new SolrException( + ErrorCode.BAD_REQUEST, + "Package name and version are both required. Actual: " + cmdArgs[0]); + } + String packageName = parsedVersion.first(); + String version = parsedVersion.second(); + packageManager.uninstall(packageName, version); + break; + } + default: + throw new RuntimeException("Unrecognized command: " + command); + } + } + @Override public String getHeader() { StringBuilder sb = new StringBuilder(); @@ -381,6 +484,61 @@ public Options getOptions() { @Override public int callTool() throws Exception { - throw new UnsupportedOperationException("This tool does not yet support PicoCli"); + String credentials = credentialsOptions.credentials; + String solrUrl = resolveSolrUrl(credentials); + String zkHost = resolveZkHost(solrUrl, credentials); + String[] args = cmdArgs == null ? new String[0] : cmdArgs; + PackageFlags packageFlags = new PackageFlags(collections, cluster, param, update, collection, noPrompt); + executePackage(solrUrl, zkHost, credentials, cmd, args, packageFlags); + return 0; + } + + private String resolveSolrUrl(String credentials) throws Exception { + if (connectionOptions != null) { + String solrUrl = connectionOptions.effectiveSolrUrl(); + if (solrUrl != null) { + return CLIUtils.normalizeSolrUrl(solrUrl); + } + String zkHost = connectionOptions.effectiveZkHost(); + if (zkHost != null) { + return CLIUtils.solrUrlFromConnection(CloudSolrClient.CloudSolrClientConnection.parse(zkHost), credentials); + } + } + String zkHostProp = EnvUtils.getProperty("zkHost"); + if (zkHostProp != null && !zkHostProp.isBlank()) { + return CLIUtils.solrUrlFromConnection(CloudSolrClient.CloudSolrClientConnection.parse(zkHostProp), credentials); + } + String defaultUrl = CLIUtils.getDefaultSolrUrl(); + CLIO.err( + "Neither --solr-connection, --zk-host or --solr-url parameters, nor SOLR_CONNECTION, ZK_HOST env var provided, so assuming solr url is " + + defaultUrl + + "."); + return defaultUrl; + } + + private String resolveZkHost(String solrUrl, String credentials) throws Exception { + if (connectionOptions != null) { + String zkHost = connectionOptions.effectiveZkHost(); + if (zkHost != null) { + return zkHost; + } + } + String zkHostProp = EnvUtils.getProperty("zkHost"); + if (zkHostProp != null && !zkHostProp.isBlank()) { + return zkHostProp; + } + try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials)) { + Map status = StatusTool.reportStatus(solrClient); + @SuppressWarnings("unchecked") + Map cloud = (Map) status.get("cloud"); + if (cloud != null) { + String zookeeper = cloud.get("ZooKeeper").toString(); + if (zookeeper != null && zookeeper.endsWith("(embedded)")) { + zookeeper = zookeeper.substring(0, zookeeper.length() - "(embedded)".length()); + } + return zookeeper; + } + } + return null; } } 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 266bb08badb6..2eb29b2aae28 100755 --- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java +++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java @@ -82,7 +82,8 @@ ZkTool.class, AuthTool.class, CreateTool.class, - DeleteTool.class + DeleteTool.class, + PackageTool.class }) public class SolrCLI implements CLIO { From f61cdebd880505260844400297aa8624536c459c Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 15 Aug 2026 13:48:37 +0530 Subject: [PATCH 02/23] minor --- solr/core/src/java/org/apache/solr/cli/PackageTool.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 a9aae6039216..3d088bbac776 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -64,8 +64,8 @@ " bin/solr package add-repo myrepo https://my.repo.example/solr-packages", "", " # Install a package and deploy it to a collection", - " bin/solr package install mypkg-1.0.0", - " bin/solr package deploy mypkg-1.0.0 --collections myCollection -y", + " bin/solr package install mypkg:1.0.0", + " bin/solr package deploy mypkg:1.0.0 --collections myCollection -y", "", " # List packages deployed on a collection", " bin/solr package list-deployed -c myCollection" @@ -149,12 +149,12 @@ record PackageFlags( @picocli.CommandLine.Option( names = {"--collections"}, paramLabel = "COLLECTIONS", - description = "Specifies that this action should affect plugins for the given collection only, excluding cluster level plugins.") + description = "Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins.") private String collections; @picocli.CommandLine.Option( names = {"--cluster"}, - description = "Specifies that this action should affect cluster level plugins only.") + description = "Specifies that this action should affect cluster-level plugins only.") private boolean cluster; @picocli.CommandLine.Option( From 86913e59b1707b80c5d4ceab38a869fd1f784cac Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 15 Aug 2026 13:49:39 +0530 Subject: [PATCH 03/23] tidying done --- .../java/org/apache/solr/cli/PackageTool.java | 181 ++++++++++-------- .../src/java/org/apache/solr/cli/SolrCLI.java | 2 +- 2 files changed, 97 insertions(+), 86 deletions(-) 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 3d088bbac776..4975378ce435 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -55,20 +55,20 @@ description = "Install, deploy and manage Solr packages in SolrCloud.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0:Operation completed successfully.", - "1:Operation failed; check output for details." + "0:Operation completed successfully.", + "1:Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # Add a package repository", - " bin/solr package add-repo myrepo https://my.repo.example/solr-packages", - "", - " # Install a package and deploy it to a collection", - " bin/solr package install mypkg:1.0.0", - " bin/solr package deploy mypkg:1.0.0 --collections myCollection -y", - "", - " # List packages deployed on a collection", - " bin/solr package list-deployed -c myCollection" + " # Add a package repository", + " bin/solr package add-repo myrepo https://my.repo.example/solr-packages", + "", + " # Install a package and deploy it to a collection", + " bin/solr package install mypkg:1.0.0", + " bin/solr package deploy mypkg:1.0.0 --collections myCollection -y", + "", + " # List packages deployed on a collection", + " bin/solr package list-deployed -c myCollection" }) public class PackageTool extends ToolBase { @@ -136,20 +136,23 @@ record PackageFlags( index = "0", arity = "1", paramLabel = "COMMAND", - description = "Package command: add-repo, add-key, list-installed, list-available, list-deployed, install, deploy, undeploy, uninstall.") + description = + "Package command: add-repo, add-key, list-installed, list-available, list-deployed, install, deploy, undeploy, uninstall.") private String cmd; @picocli.CommandLine.Parameters( index = "1..*", arity = "0..*", paramLabel = "ARGS", - description = "Command-specific arguments (package name[:version], repository name/URL, key file, etc.).") + description = + "Command-specific arguments (package name[:version], repository name/URL, key file, etc.).") private String[] cmdArgs; @picocli.CommandLine.Option( names = {"--collections"}, paramLabel = "COLLECTIONS", - description = "Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins.") + description = + "Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins.") private String collections; @picocli.CommandLine.Option( @@ -208,13 +211,14 @@ public void runImpl(CommandLine cli) throws Exception { String credentials = cli.getOptionValue(CommonCLIOptions.CREDENTIALS_OPTION); String command = cli.getArgs()[0]; String[] cmdArgs = Arrays.copyOfRange(cli.getArgs(), 1, cli.getArgs().length); - PackageFlags packageFlags = new PackageFlags( - cli.getOptionValue(COLLECTIONS_OPTION), - cli.hasOption(CLUSTER_OPTION), - cli.getOptionValues(PARAM_OPTION), - cli.hasOption(UPDATE_OPTION), - cli.getOptionValue(COLLECTION_OPTION), - cli.hasOption(NO_PROMPT_OPTION)); + PackageFlags packageFlags = + new PackageFlags( + cli.getOptionValue(COLLECTIONS_OPTION), + cli.hasOption(CLUSTER_OPTION), + cli.getOptionValues(PARAM_OPTION), + cli.hasOption(UPDATE_OPTION), + cli.getOptionValue(COLLECTION_OPTION), + cli.hasOption(NO_PROMPT_OPTION)); executePackage(solrUrl, zkHost, credentials, command, cmdArgs, packageFlags); } @@ -225,7 +229,8 @@ private void executePackage( String credentials, String command, String[] cmdArgs, - PackageFlags packageFlags) throws Exception { + PackageFlags packageFlags) + throws Exception { // Need a logging free, clean output going through to the user. Level oldLevel = LoggerContext.getContext(false).getRootLogger().getLevel(); @@ -260,7 +265,8 @@ private void executePackage( } } - private void handleCommand(String command, String[] cmdArgs, PackageFlags packageFlags) throws Exception { + private void handleCommand(String command, String[] cmdArgs, PackageFlags packageFlags) + throws Exception { switch (command) { case "add-repo": String repoName = cmdArgs[0]; @@ -322,74 +328,76 @@ private void handleCommand(String command, String[] cmdArgs, PackageFlags packag } break; case "install": - { - Pair parsedVersion = parsePackageVersion(cmdArgs[0]); - String packageName = parsedVersion.first(); - String version = parsedVersion.second(); - boolean success = repositoryManager.install(packageName, version); - if (success) { - printGreen(packageName + " installed."); - } else { - printRed(packageName + " installation failed."); - } - break; - } - case "deploy": - { - if (packageFlags.cluster() || packageFlags.collections() != null) { + { Pair parsedVersion = parsePackageVersion(cmdArgs[0]); String packageName = parsedVersion.first(); String version = parsedVersion.second(); - String[] collections = packageFlags.collections() != null - ? PackageUtils.validateCollections(packageFlags.collections().split(",")) - : new String[] {}; - packageManager.deploy( - packageName, - version, - collections, - packageFlags.cluster(), - packageFlags.parameters(), - packageFlags.update(), - packageFlags.noPrompt()); - } else { - printRed( - "Either specify --cluster to deploy cluster level plugins or --collections to deploy collection level plugins"); + boolean success = repositoryManager.install(packageName, version); + if (success) { + printGreen(packageName + " installed."); + } else { + printRed(packageName + " installation failed."); + } + break; + } + case "deploy": + { + if (packageFlags.cluster() || packageFlags.collections() != null) { + Pair parsedVersion = parsePackageVersion(cmdArgs[0]); + String packageName = parsedVersion.first(); + String version = parsedVersion.second(); + String[] collections = + packageFlags.collections() != null + ? PackageUtils.validateCollections(packageFlags.collections().split(",")) + : new String[] {}; + packageManager.deploy( + packageName, + version, + collections, + packageFlags.cluster(), + packageFlags.parameters(), + packageFlags.update(), + packageFlags.noPrompt()); + } else { + printRed( + "Either specify --cluster to deploy cluster level plugins or --collections to deploy collection level plugins"); + } + break; } - break; - } case "undeploy": - { - if (packageFlags.cluster() || packageFlags.collections() != null) { + { + if (packageFlags.cluster() || packageFlags.collections() != null) { + Pair parsedVersion = parsePackageVersion(cmdArgs[0]); + if (parsedVersion.second() != null) { + throw new SolrException( + ErrorCode.BAD_REQUEST, + "Only package name expected, without a version. Actual: " + cmdArgs[0]); + } + String packageName = parsedVersion.first(); + String[] collections = + packageFlags.collections() != null + ? PackageUtils.validateCollections(packageFlags.collections().split(",")) + : new String[] {}; + packageManager.undeploy(packageName, collections, packageFlags.cluster()); + } else { + printRed( + "Either specify --cluster to undeploy cluster level plugins or -collections to undeploy collection level plugins"); + } + break; + } + case "uninstall": + { Pair parsedVersion = parsePackageVersion(cmdArgs[0]); - if (parsedVersion.second() != null) { + if (parsedVersion.second() == null) { throw new SolrException( ErrorCode.BAD_REQUEST, - "Only package name expected, without a version. Actual: " + cmdArgs[0]); + "Package name and version are both required. Actual: " + cmdArgs[0]); } String packageName = parsedVersion.first(); - String[] collections = packageFlags.collections() != null - ? PackageUtils.validateCollections(packageFlags.collections().split(",")) - : new String[] {}; - packageManager.undeploy(packageName, collections, packageFlags.cluster()); - } else { - printRed( - "Either specify --cluster to undeploy cluster level plugins or -collections to undeploy collection level plugins"); - } - break; - } - case "uninstall": - { - Pair parsedVersion = parsePackageVersion(cmdArgs[0]); - if (parsedVersion.second() == null) { - throw new SolrException( - ErrorCode.BAD_REQUEST, - "Package name and version are both required. Actual: " + cmdArgs[0]); + String version = parsedVersion.second(); + packageManager.uninstall(packageName, version); + break; } - String packageName = parsedVersion.first(); - String version = parsedVersion.second(); - packageManager.uninstall(packageName, version); - break; - } default: throw new RuntimeException("Unrecognized command: " + command); } @@ -488,7 +496,8 @@ public int callTool() throws Exception { String solrUrl = resolveSolrUrl(credentials); String zkHost = resolveZkHost(solrUrl, credentials); String[] args = cmdArgs == null ? new String[0] : cmdArgs; - PackageFlags packageFlags = new PackageFlags(collections, cluster, param, update, collection, noPrompt); + PackageFlags packageFlags = + new PackageFlags(collections, cluster, param, update, collection, noPrompt); executePackage(solrUrl, zkHost, credentials, cmd, args, packageFlags); return 0; } @@ -501,18 +510,20 @@ private String resolveSolrUrl(String credentials) throws Exception { } String zkHost = connectionOptions.effectiveZkHost(); if (zkHost != null) { - return CLIUtils.solrUrlFromConnection(CloudSolrClient.CloudSolrClientConnection.parse(zkHost), credentials); + return CLIUtils.solrUrlFromConnection( + CloudSolrClient.CloudSolrClientConnection.parse(zkHost), credentials); } } String zkHostProp = EnvUtils.getProperty("zkHost"); if (zkHostProp != null && !zkHostProp.isBlank()) { - return CLIUtils.solrUrlFromConnection(CloudSolrClient.CloudSolrClientConnection.parse(zkHostProp), credentials); + return CLIUtils.solrUrlFromConnection( + CloudSolrClient.CloudSolrClientConnection.parse(zkHostProp), credentials); } String defaultUrl = CLIUtils.getDefaultSolrUrl(); CLIO.err( "Neither --solr-connection, --zk-host or --solr-url parameters, nor SOLR_CONNECTION, ZK_HOST env var provided, so assuming solr url is " - + defaultUrl - + "."); + + defaultUrl + + "."); return defaultUrl; } 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 2eb29b2aae28..263dc54dce30 100755 --- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java +++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java @@ -83,7 +83,7 @@ AuthTool.class, CreateTool.class, DeleteTool.class, - PackageTool.class + PackageTool.class }) public class SolrCLI implements CLIO { From 124256ca94c5f0d71c92c7f944babef19bb07775 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 15 Aug 2026 16:58:35 +0530 Subject: [PATCH 04/23] generated cli docs --- .../deployment-guide/deployment-nav.adoc | 1 + .../pages/cli/solr-package.adoc | 130 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc diff --git a/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc b/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc index 5f83b0407404..fb90bd82b38b 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc @@ -22,6 +22,7 @@ ** xref:cli/solr-auth.adoc[auth] ** xref:cli/solr-create.adoc[create] ** xref:cli/solr-delete.adoc[delete] +** xref:cli/solr-package.adoc[package] ** xref:cli/solr-start.adoc[start] ** xref:cli/solr-status.adoc[status] ** xref:cli/solr-stop.adoc[stop] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc new file mode 100644 index 000000000000..6190d55eed44 --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc @@ -0,0 +1,130 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package +:page-toclevels: 2 + +// tag::picocli-generated-man-section-name[] +== Name + +bin/solr package - Install, deploy and manage Solr packages in SolrCloud. + +// end::picocli-generated-man-section-name[] + +// tag::picocli-generated-man-section-synopsis[] +== Synopsis + +.... +bin/solr package [-vy] [--cluster] [--update] [-c=COLLECTION] + [--collections=COLLECTIONS] [-u=] [--param=PARAMS]... + [-s= | --solr-url= | -z=] COMMAND + [ARGS...] +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Install, deploy and manage Solr packages in SolrCloud. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-c*, *--collection*=_COLLECTION_:: + The collection to apply the package to. + +*--cluster*:: + Specifies that this action should affect cluster-level plugins only. + +*--collections*=_COLLECTIONS_:: + Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins. + +*--param*=_PARAMS_:: + List of parameters to be used with the deploy command. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*--update*:: + If a deployment is an update over a previous deployment. + +*-v*, *--verbose*:: + Enable verbose mode. + +*-y*, *--no-prompt*:: + Don't prompt for input; accept all default choices, defaults to false. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +_COMMAND_:: + Package command: add-repo, add-key, list-installed, list-available, list-deployed, install, deploy, undeploy, uninstall. + +[_ARGS_...]:: + Command-specific arguments (package name[:version], repository name/URL, key file, etc.). + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-commands[] +// end::picocli-generated-man-section-commands[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes: + +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples: + +[%hardbreaks] + # Add a package repository + bin/solr package add-repo myrepo https://my.repo.example/bin/solr packages + +[%hardbreaks] + # Install a package and deploy it to a collection + bin/solr package install mypkg:1.0.0 + bin/solr package deploy mypkg:1.0.0 --collections myCollection -y + +[%hardbreaks] + # List packages deployed on a collection + bin/solr package list-deployed -c myCollection + +// end::picocli-generated-man-section-footer[] From 4e2e52822f5f23341866e25d30d11149365f9587 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 15 Aug 2026 18:30:54 +0530 Subject: [PATCH 05/23] tests --- .../solr/cli/PackageToolPicocliTest.java | 34 ++++++++ .../org/apache/solr/cli/PackageToolTest.java | 79 ++++++++----------- 2 files changed, 65 insertions(+), 48 deletions(-) create mode 100644 solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java diff --git a/solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java b/solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java new file mode 100644 index 000000000000..70d0ccc7ccb2 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package org.apache.solr.cli; + +import picocli.CommandLine; + +/** + * Runs all {@link PackageToolTest} tests through the picocli invocation path. + */ +public class PackageToolPicocliTest extends PackageToolTest { + + @Override + protected int runTool(String[] args, ToolRuntime runtime) throws Exception { + PackageTool tool = new PackageTool(runtime); + return new CommandLine(tool) + .setDefaultValueProvider(new CliDefaultValueProvider()) + .execute(args); + } +} diff --git a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java index 9282af37e520..abb8be0f7a52 100644 --- a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java +++ b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java @@ -89,21 +89,21 @@ private > T withBasicAuth(T req) { return req; } - @Test - public void testPackageTool() throws Exception { - ToolRuntime runtime = new CLITestHelper.TestingRuntime(false); + protected int runTool(String[] args, ToolRuntime runtime) throws Exception { PackageTool tool = new PackageTool(runtime); + return tool.runTool(SolrCLI.processCommandLineArgs(tool, args)); + } + @Test + public void testPackageTool() throws Exception { String solrUrl = cluster.getJettySolrRunner(0).getBaseUrl().toString(); run( - tool, new String[] { "--solr-url", solrUrl, "list-installed", "--credentials", SecurityJson.USER_PASS }); run( - tool, new String[] { "--solr-url", solrUrl, @@ -115,13 +115,11 @@ public void testPackageTool() throws Exception { }); run( - tool, new String[] { "--solr-url", solrUrl, "list-available", "--credentials", SecurityJson.USER_PASS }); run( - tool, new String[] { "--solr-url", solrUrl, @@ -132,7 +130,6 @@ public void testPackageTool() throws Exception { }); run( - tool, new String[] { "--solr-url", solrUrl, "list-installed", "--credentials", SecurityJson.USER_PASS }); @@ -145,7 +142,6 @@ public void testPackageTool() throws Exception { String rhPath = "/mypath2"; run( - tool, new String[] { "--solr-url", solrUrl, @@ -157,7 +153,6 @@ public void testPackageTool() throws Exception { // Leaving -p in for --param to test the deprecated value continues to work. run( - tool, new String[] { "--solr-url", solrUrl, @@ -175,7 +170,6 @@ public void testPackageTool() throws Exception { "abc", "question-answer", "1.0.0", rhPath, "1.0.0", SecurityJson.USER_PASS); run( - tool, new String[] { "--solr-url", solrUrl, @@ -186,7 +180,6 @@ public void testPackageTool() throws Exception { }); run( - tool, new String[] { "--solr-url", solrUrl, @@ -206,7 +199,6 @@ public void testPackageTool() throws Exception { // This command pegs the version to the latest available run( - tool, new String[] { "--solr-url", solrUrl, @@ -222,7 +214,6 @@ public void testPackageTool() throws Exception { "abc", "question-answer", "$LATEST", rhPath, "1.0.0", SecurityJson.USER_PASS); run( - tool, new String[] { "--solr-url", solrUrl, @@ -237,7 +228,6 @@ public void testPackageTool() throws Exception { log.info("Testing explicit deployment to a different/newer version"); run( - tool, new String[] { "--solr-url", solrUrl, @@ -252,7 +242,6 @@ public void testPackageTool() throws Exception { // even if parameters are not passed in, they should be picked up from previous deployment if (random().nextBoolean()) { run( - tool, new String[] { "--solr-url", solrUrl, @@ -269,7 +258,6 @@ public void testPackageTool() throws Exception { }); } else { run( - tool, new String[] { "--solr-url", solrUrl, @@ -289,7 +277,6 @@ public void testPackageTool() throws Exception { log.info("Running undeploy..."); run( - tool, new String[] { "--solr-url", solrUrl, @@ -302,7 +289,6 @@ public void testPackageTool() throws Exception { }); run( - tool, new String[] { "--solr-url", solrUrl, @@ -382,23 +368,21 @@ public void testDeployValidationMessages() throws Exception { .processAndWait(cluster.getSolrClient(), 10); CLITestHelper.TestingRuntime captureRuntime = new CLITestHelper.TestingRuntime(true); - PackageTool tool = new PackageTool(captureRuntime); // Collection exists but package does not — collection validation should pass, // package lookup should fail. - tool.runTool( - SolrCLI.processCommandLineArgs( - tool, - new String[] { - "--solr-url", - solrUrl, - "deploy", - "NONEXISTENT_PKG", - "--collections", - "validation-test", - "--credentials", - SecurityJson.USER_PASS - })); + runTool( + new String[] { + "--solr-url", + solrUrl, + "deploy", + "NONEXISTENT_PKG", + "--collections", + "validation-test", + "--credentials", + SecurityJson.USER_PASS + }, + captureRuntime); String deployOut = captureRuntime.getOutput(); assertFalse( "Should not complain about invalid collection", deployOut.contains("Invalid collection")); @@ -409,19 +393,18 @@ public void testDeployValidationMessages() throws Exception { captureRuntime.clearOutput(); // Undeploy of a package that was never deployed should give a clear message. - tool.runTool( - SolrCLI.processCommandLineArgs( - tool, - new String[] { - "--solr-url", - solrUrl, - "undeploy", - "NONEXISTENT_PKG", - "--collections", - "validation-test", - "--credentials", - SecurityJson.USER_PASS - })); + runTool( + new String[] { + "--solr-url", + solrUrl, + "undeploy", + "NONEXISTENT_PKG", + "--collections", + "validation-test", + "--credentials", + SecurityJson.USER_PASS + }, + captureRuntime); String undeployOut = captureRuntime.getOutput(); assertFalse( "Should not complain about invalid collection", undeployOut.contains("Invalid collection")); @@ -430,8 +413,8 @@ public void testDeployValidationMessages() throws Exception { undeployOut.contains("Package NONEXISTENT_PKG not deployed on collection validation-test")); } - private void run(PackageTool tool, String[] args) throws Exception { - int res = tool.runTool(SolrCLI.processCommandLineArgs(tool, args)); + private void run(String[] args) throws Exception { + int res = runTool(args, new CLITestHelper.TestingRuntime(false)); assertEquals("Non-zero status returned for: " + Arrays.toString(args), 0, res); } From e9cefa86183d80cf24fc12bb44448c1ecf9ada8a Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 23 Aug 2026 03:00:06 +0530 Subject: [PATCH 06/23] fixed url --- solr/core/src/java/org/apache/solr/cli/PackageTool.java | 2 +- .../modules/deployment-guide/pages/cli/solr-package.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 4975378ce435..71b464e86d7a 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -61,7 +61,7 @@ footerHeading = "%nExamples:%n", footer = { " # Add a package repository", - " bin/solr package add-repo myrepo https://my.repo.example/solr-packages", + " bin/solr package add-repo myrepo https://my.repo.example/repo", "", " # Install a package and deploy it to a collection", " bin/solr package install mypkg:1.0.0", diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc index 6190d55eed44..4fa12edb6ce8 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc @@ -116,7 +116,7 @@ _COMMAND_:: [%hardbreaks] # Add a package repository - bin/solr package add-repo myrepo https://my.repo.example/bin/solr packages + bin/solr package add-repo myrepo https://my.repo.example/repo [%hardbreaks] # Install a package and deploy it to a collection From 5e76d9270e897256e0f244dc9351c63022beec85 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 23 Aug 2026 03:35:23 +0530 Subject: [PATCH 07/23] help added --- solr/core/src/java/org/apache/solr/cli/PackageTool.java | 2 ++ 1 file changed, 2 insertions(+) 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 71b464e86d7a..5868a60ca4e8 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -127,6 +127,8 @@ record PackageFlags( // --- picocli fields --- + @picocli.CommandLine.Mixin private HelpMixin helpMixin; + @picocli.CommandLine.ArgGroup(exclusive = true, multiplicity = "0..1") private ConnectionOptions connectionOptions; From ed3602d3ffe93c364d75b480a980c76c2bb5ed04 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 5 Sep 2026 20:37:39 +0530 Subject: [PATCH 08/23] subcommmands --- solr/core/src/java/org/apache/solr/cli/AddKey.java | 5 +++++ solr/core/src/java/org/apache/solr/cli/AddRepo.java | 5 +++++ solr/core/src/java/org/apache/solr/cli/Deploy.java | 4 ++++ solr/core/src/java/org/apache/solr/cli/Install.java | 4 ++++ .../src/java/org/apache/solr/cli/ListAvailable.java | 4 ++++ .../src/java/org/apache/solr/cli/ListDeployed.java | 4 ++++ .../src/java/org/apache/solr/cli/ListInstalled.java | 4 ++++ .../src/java/org/apache/solr/cli/PackageTool.java | 13 ++++++++++++- .../core/src/java/org/apache/solr/cli/Undeploy.java | 4 ++++ .../src/java/org/apache/solr/cli/Uninstall.java | 4 ++++ 10 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 solr/core/src/java/org/apache/solr/cli/AddKey.java create mode 100644 solr/core/src/java/org/apache/solr/cli/AddRepo.java create mode 100644 solr/core/src/java/org/apache/solr/cli/Deploy.java create mode 100644 solr/core/src/java/org/apache/solr/cli/Install.java create mode 100644 solr/core/src/java/org/apache/solr/cli/ListAvailable.java create mode 100644 solr/core/src/java/org/apache/solr/cli/ListDeployed.java create mode 100644 solr/core/src/java/org/apache/solr/cli/ListInstalled.java create mode 100644 solr/core/src/java/org/apache/solr/cli/Undeploy.java create mode 100644 solr/core/src/java/org/apache/solr/cli/Uninstall.java diff --git a/solr/core/src/java/org/apache/solr/cli/AddKey.java b/solr/core/src/java/org/apache/solr/cli/AddKey.java new file mode 100644 index 000000000000..1f39d039f4ad --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/AddKey.java @@ -0,0 +1,5 @@ +package org.apache.solr.cli; + +public class AddKey { + +} diff --git a/solr/core/src/java/org/apache/solr/cli/AddRepo.java b/solr/core/src/java/org/apache/solr/cli/AddRepo.java new file mode 100644 index 000000000000..56f43e26a53f --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/AddRepo.java @@ -0,0 +1,5 @@ +package org.apache.solr.cli; + +public class AddRepo { + +} diff --git a/solr/core/src/java/org/apache/solr/cli/Deploy.java b/solr/core/src/java/org/apache/solr/cli/Deploy.java new file mode 100644 index 000000000000..bdc2ec2a9909 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/Deploy.java @@ -0,0 +1,4 @@ +package org.apache.solr.cli; + +public class Deploy { +} diff --git a/solr/core/src/java/org/apache/solr/cli/Install.java b/solr/core/src/java/org/apache/solr/cli/Install.java new file mode 100644 index 000000000000..83e88cd74d39 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/Install.java @@ -0,0 +1,4 @@ +package org.apache.solr.cli; + +public class Install { +} diff --git a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java new file mode 100644 index 000000000000..48ed0c698c08 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java @@ -0,0 +1,4 @@ +package org.apache.solr.cli; + +public class ListAvailable { +} diff --git a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java new file mode 100644 index 000000000000..e288867ba9b5 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java @@ -0,0 +1,4 @@ +package org.apache.solr.cli; + +public class ListDeployed { +} diff --git a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java new file mode 100644 index 000000000000..fbd579093aa0 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java @@ -0,0 +1,4 @@ +package org.apache.solr.cli; + +public class ListInstalled { +} 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 5868a60ca4e8..3deb6dd61822 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -52,13 +52,24 @@ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "package", - description = "Install, deploy and manage Solr packages in SolrCloud.", + description = "Sub commands to Install, deploy and manage Solr packages in SolrCloud.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { "0:Operation completed successfully.", "1:Operation failed; check output for details." }, footerHeading = "%nExamples:%n", + subcommands = { + AddRepo.class, + AddKey.class, + ListAvailable.class, + ListInstalled.class, + ListDeployed.class, + Install.class, + Deploy.class, + Uninstall.class, + Undeploy.class + }, footer = { " # Add a package repository", " bin/solr package add-repo myrepo https://my.repo.example/repo", diff --git a/solr/core/src/java/org/apache/solr/cli/Undeploy.java b/solr/core/src/java/org/apache/solr/cli/Undeploy.java new file mode 100644 index 000000000000..81a703cfffdf --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/Undeploy.java @@ -0,0 +1,4 @@ +package org.apache.solr.cli; + +public class Undeploy { +} diff --git a/solr/core/src/java/org/apache/solr/cli/Uninstall.java b/solr/core/src/java/org/apache/solr/cli/Uninstall.java new file mode 100644 index 000000000000..c2e9e62411bc --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/Uninstall.java @@ -0,0 +1,4 @@ +package org.apache.solr.cli; + +public class Uninstall { +} From 70980649727422b71e598623e956af51d5549b92 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 5 Sep 2026 23:37:56 +0530 Subject: [PATCH 09/23] tried outs --- .../src/java/org/apache/solr/cli/AddRepo.java | 46 ++++++++++++++++++- .../java/org/apache/solr/cli/PackageTool.java | 10 +--- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/AddRepo.java b/solr/core/src/java/org/apache/solr/cli/AddRepo.java index 56f43e26a53f..8633d9d58594 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddRepo.java +++ b/solr/core/src/java/org/apache/solr/cli/AddRepo.java @@ -1,5 +1,49 @@ package org.apache.solr.cli; -public class AddRepo { +import org.apache.commons.cli.CommandLine; +import org.apache.solr.packagemanager.PackageManager; +import org.apache.solr.packagemanager.RepositoryManager; +import static org.apache.solr.packagemanager.PackageUtils.format; +import static org.apache.solr.packagemanager.PackageUtils.formatGreen; + +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "add-repo", + description = "Command to add repository for package management in SolrCloud.", + footerHeading = "%nExamples:%n", + footer = { + " # Add a package repository", + " bin/solr package add-repo myrepo https://my.repo.example/repo", + }) +public class AddRepo extends ToolBase { + + public PackageManager packageManager; + public RepositoryManager repositoryManager; + + @Override + public void runImpl(CommandLine cli) throws Exception { + + } + + @Override + public int callTool() throws Exception { + return 0; + } + + @Override + public String getName() { + return "add-repo"; + } + + @Override + public String getHeader() { + StringBuilder sb = new StringBuilder(); + format(sb, "Package Manager\n---------------"); + formatGreen(sb, "bin/solr package add-repo "); + format(sb, "Add a repository to Solr."); + format(sb, ""); + return sb.toString(); + } } 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 3deb6dd61822..0031671c279f 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -60,15 +60,7 @@ }, footerHeading = "%nExamples:%n", subcommands = { - AddRepo.class, - AddKey.class, - ListAvailable.class, - ListInstalled.class, - ListDeployed.class, - Install.class, - Deploy.class, - Uninstall.class, - Undeploy.class + AddRepo.class }, footer = { " # Add a package repository", From 65b418724ca60f860f52694db15266948421f3c6 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 7 Sep 2026 00:19:41 +0530 Subject: [PATCH 10/23] changes --- .../src/java/org/apache/solr/cli/AddRepo.java | 77 +++++++++++++++++-- .../java/org/apache/solr/cli/PackageTool.java | 4 +- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/AddRepo.java b/solr/core/src/java/org/apache/solr/cli/AddRepo.java index 8633d9d58594..45114df82065 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddRepo.java +++ b/solr/core/src/java/org/apache/solr/cli/AddRepo.java @@ -1,17 +1,23 @@ package org.apache.solr.cli; +import static org.apache.solr.cli.SolrCLI.printGreen; +import static org.apache.solr.packagemanager.PackageUtils.format; +import static org.apache.solr.packagemanager.PackageUtils.formatGreen; + import org.apache.commons.cli.CommandLine; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.Configurator; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.common.SolrException; import org.apache.solr.packagemanager.PackageManager; import org.apache.solr.packagemanager.RepositoryManager; -import static org.apache.solr.packagemanager.PackageUtils.format; -import static org.apache.solr.packagemanager.PackageUtils.formatGreen; - /** Supports package add-repo command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "add-repo", - description = "Command to add repository for package management in SolrCloud.", + description = "Add a package repository to Solr.", footerHeading = "%nExamples:%n", footer = { " # Add a package repository", @@ -19,16 +25,44 @@ }) public class AddRepo extends ToolBase { - public PackageManager packageManager; - public RepositoryManager repositoryManager; + @picocli.CommandLine.ParentCommand private PackageTool packageTool; + + @picocli.CommandLine.Mixin private HelpMixin helpMixin; + @picocli.CommandLine.Mixin private CredentialsOptions credentialsOptions; + + @picocli.CommandLine.ArgGroup private ConnectionOptions connectionOptions; + + @picocli.CommandLine.Parameters( + index = "0", + arity = "1", + paramLabel = "REPOSITORY-NAME") + private String repoName; + + @picocli.CommandLine.Parameters( + index = "1", + arity = "1", + paramLabel = "REPOSITORY-URL") + private String repoUrl; + + public AddRepo() { + this(new DefaultToolRuntime()); + } + + public AddRepo(ToolRuntime runtime) { + super(runtime); + } @Override public void runImpl(CommandLine cli) throws Exception { - + throw new UnsupportedOperationException("add-repo is implemented via the commons-cli path under PackageTool"); } @Override public int callTool() throws Exception { + String credentials = credentialsOptions.credentials; + String solrUrl = packageTool.resolveSolrUrl(credentials); + String zkHost = packageTool.resolveZkHost(solrUrl, credentials); + addRepo(solrUrl, zkHost, credentials, repoName, repoUrl); return 0; } @@ -46,4 +80,33 @@ public String getHeader() { format(sb, ""); return sb.toString(); } + + private void addRepo(String solrUrl, String zkHost, String credentials, String repoName, String repoUrl) throws Exception { + Level oldLevel = LoggerContext.getContext(false).getRootLogger().getLevel(); + Configurator.setRootLevel(Level.OFF); + + try { + if (zkHost == null) { + throw new SolrException(SolrException.ErrorCode.INVALID_STATE, "Package manager only runs in SolrCloud"); + } + + + try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials, true)) { + PackageManager packageManager = new PackageManager(packageTool.getRuntime(), solrClient, solrUrl, zkHost); + try { + RepositoryManager repositoryManager = new RepositoryManager(solrClient, packageManager); + repositoryManager.addRepository(repoName, repoUrl); + printGreen("Added repository: " + repoName); + } finally { + packageManager.close(); + } + } + } catch (Exception exception) { + exception.printStackTrace(System.err); + throw exception; + } finally { + Configurator.setRootLevel(oldLevel); + } + + } } 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 0031671c279f..246dedadd972 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -507,7 +507,7 @@ public int callTool() throws Exception { return 0; } - private String resolveSolrUrl(String credentials) throws Exception { + String resolveSolrUrl(String credentials) throws Exception { if (connectionOptions != null) { String solrUrl = connectionOptions.effectiveSolrUrl(); if (solrUrl != null) { @@ -532,7 +532,7 @@ private String resolveSolrUrl(String credentials) throws Exception { return defaultUrl; } - private String resolveZkHost(String solrUrl, String credentials) throws Exception { + String resolveZkHost(String solrUrl, String credentials) throws Exception { if (connectionOptions != null) { String zkHost = connectionOptions.effectiveZkHost(); if (zkHost != null) { From 60f3592bd93514b7d07d25f6df41d96b60a4227a Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 7 Sep 2026 00:34:33 +0530 Subject: [PATCH 11/23] licenses --- .../src/java/org/apache/solr/cli/AddKey.java | 17 +++++++++++++++++ .../src/java/org/apache/solr/cli/AddRepo.java | 17 +++++++++++++++++ .../src/java/org/apache/solr/cli/Deploy.java | 17 +++++++++++++++++ .../src/java/org/apache/solr/cli/Install.java | 17 +++++++++++++++++ .../java/org/apache/solr/cli/ListAvailable.java | 17 +++++++++++++++++ .../java/org/apache/solr/cli/ListDeployed.java | 17 +++++++++++++++++ .../java/org/apache/solr/cli/ListInstalled.java | 17 +++++++++++++++++ .../src/java/org/apache/solr/cli/Undeploy.java | 17 +++++++++++++++++ .../src/java/org/apache/solr/cli/Uninstall.java | 17 +++++++++++++++++ 9 files changed, 153 insertions(+) diff --git a/solr/core/src/java/org/apache/solr/cli/AddKey.java b/solr/core/src/java/org/apache/solr/cli/AddKey.java index 1f39d039f4ad..a8b826380a33 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddKey.java +++ b/solr/core/src/java/org/apache/solr/cli/AddKey.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; public class AddKey { diff --git a/solr/core/src/java/org/apache/solr/cli/AddRepo.java b/solr/core/src/java/org/apache/solr/cli/AddRepo.java index 45114df82065..71fcc61f30ec 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddRepo.java +++ b/solr/core/src/java/org/apache/solr/cli/AddRepo.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; import static org.apache.solr.cli.SolrCLI.printGreen; diff --git a/solr/core/src/java/org/apache/solr/cli/Deploy.java b/solr/core/src/java/org/apache/solr/cli/Deploy.java index bdc2ec2a9909..b3e726092877 100644 --- a/solr/core/src/java/org/apache/solr/cli/Deploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Deploy.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; public class Deploy { diff --git a/solr/core/src/java/org/apache/solr/cli/Install.java b/solr/core/src/java/org/apache/solr/cli/Install.java index 83e88cd74d39..02e65fde9d7a 100644 --- a/solr/core/src/java/org/apache/solr/cli/Install.java +++ b/solr/core/src/java/org/apache/solr/cli/Install.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; public class Install { diff --git a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java index 48ed0c698c08..18bff1b4ce4b 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java +++ b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; public class ListAvailable { diff --git a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java index e288867ba9b5..bbaf00dd85be 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java +++ b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; public class ListDeployed { diff --git a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java index fbd579093aa0..b99b403d7f30 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java +++ b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; public class ListInstalled { diff --git a/solr/core/src/java/org/apache/solr/cli/Undeploy.java b/solr/core/src/java/org/apache/solr/cli/Undeploy.java index 81a703cfffdf..c9dba5324547 100644 --- a/solr/core/src/java/org/apache/solr/cli/Undeploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Undeploy.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; public class Undeploy { diff --git a/solr/core/src/java/org/apache/solr/cli/Uninstall.java b/solr/core/src/java/org/apache/solr/cli/Uninstall.java index c2e9e62411bc..f857e2020670 100644 --- a/solr/core/src/java/org/apache/solr/cli/Uninstall.java +++ b/solr/core/src/java/org/apache/solr/cli/Uninstall.java @@ -1,3 +1,20 @@ +/* + * 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. + */ + package org.apache.solr.cli; public class Uninstall { From c566d3c6f03740a46fed1858697d6831139c4954 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 7 Sep 2026 00:35:41 +0530 Subject: [PATCH 12/23] tidy --- .../src/java/org/apache/solr/cli/AddKey.java | 4 +- .../src/java/org/apache/solr/cli/AddRepo.java | 37 +++++++++---------- .../src/java/org/apache/solr/cli/Deploy.java | 3 +- .../src/java/org/apache/solr/cli/Install.java | 3 +- .../org/apache/solr/cli/ListAvailable.java | 3 +- .../org/apache/solr/cli/ListDeployed.java | 3 +- .../org/apache/solr/cli/ListInstalled.java | 3 +- .../java/org/apache/solr/cli/PackageTool.java | 4 +- .../java/org/apache/solr/cli/Undeploy.java | 3 +- .../java/org/apache/solr/cli/Uninstall.java | 3 +- .../solr/cli/PackageToolPicocliTest.java | 4 +- .../org/apache/solr/cli/PackageToolTest.java | 32 ++++++++-------- 12 files changed, 43 insertions(+), 59 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/AddKey.java b/solr/core/src/java/org/apache/solr/cli/AddKey.java index a8b826380a33..1d50ac39fd5c 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddKey.java +++ b/solr/core/src/java/org/apache/solr/cli/AddKey.java @@ -17,6 +17,4 @@ package org.apache.solr.cli; -public class AddKey { - -} +public class AddKey {} diff --git a/solr/core/src/java/org/apache/solr/cli/AddRepo.java b/solr/core/src/java/org/apache/solr/cli/AddRepo.java index 71fcc61f30ec..c1825323e809 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddRepo.java +++ b/solr/core/src/java/org/apache/solr/cli/AddRepo.java @@ -37,8 +37,8 @@ description = "Add a package repository to Solr.", footerHeading = "%nExamples:%n", footer = { - " # Add a package repository", - " bin/solr package add-repo myrepo https://my.repo.example/repo", + " # Add a package repository", + " bin/solr package add-repo myrepo https://my.repo.example/repo", }) public class AddRepo extends ToolBase { @@ -49,16 +49,10 @@ public class AddRepo extends ToolBase { @picocli.CommandLine.ArgGroup private ConnectionOptions connectionOptions; - @picocli.CommandLine.Parameters( - index = "0", - arity = "1", - paramLabel = "REPOSITORY-NAME") + @picocli.CommandLine.Parameters(index = "0", arity = "1", paramLabel = "REPOSITORY-NAME") private String repoName; - @picocli.CommandLine.Parameters( - index = "1", - arity = "1", - paramLabel = "REPOSITORY-URL") + @picocli.CommandLine.Parameters(index = "1", arity = "1", paramLabel = "REPOSITORY-URL") private String repoUrl; public AddRepo() { @@ -71,7 +65,8 @@ public AddRepo(ToolRuntime runtime) { @Override public void runImpl(CommandLine cli) throws Exception { - throw new UnsupportedOperationException("add-repo is implemented via the commons-cli path under PackageTool"); + throw new UnsupportedOperationException( + "add-repo is implemented via the commons-cli path under PackageTool"); } @Override @@ -98,24 +93,27 @@ public String getHeader() { return sb.toString(); } - private void addRepo(String solrUrl, String zkHost, String credentials, String repoName, String repoUrl) throws Exception { + private void addRepo( + String solrUrl, String zkHost, String credentials, String repoName, String repoUrl) + throws Exception { Level oldLevel = LoggerContext.getContext(false).getRootLogger().getLevel(); Configurator.setRootLevel(Level.OFF); try { if (zkHost == null) { - throw new SolrException(SolrException.ErrorCode.INVALID_STATE, "Package manager only runs in SolrCloud"); + throw new SolrException( + SolrException.ErrorCode.INVALID_STATE, "Package manager only runs in SolrCloud"); } - try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials, true)) { - PackageManager packageManager = new PackageManager(packageTool.getRuntime(), solrClient, solrUrl, zkHost); + PackageManager packageManager = + new PackageManager(packageTool.getRuntime(), solrClient, solrUrl, zkHost); try { - RepositoryManager repositoryManager = new RepositoryManager(solrClient, packageManager); - repositoryManager.addRepository(repoName, repoUrl); - printGreen("Added repository: " + repoName); + RepositoryManager repositoryManager = new RepositoryManager(solrClient, packageManager); + repositoryManager.addRepository(repoName, repoUrl); + printGreen("Added repository: " + repoName); } finally { - packageManager.close(); + packageManager.close(); } } } catch (Exception exception) { @@ -124,6 +122,5 @@ private void addRepo(String solrUrl, String zkHost, String credentials, String r } finally { Configurator.setRootLevel(oldLevel); } - } } diff --git a/solr/core/src/java/org/apache/solr/cli/Deploy.java b/solr/core/src/java/org/apache/solr/cli/Deploy.java index b3e726092877..7362226e7e1d 100644 --- a/solr/core/src/java/org/apache/solr/cli/Deploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Deploy.java @@ -17,5 +17,4 @@ package org.apache.solr.cli; -public class Deploy { -} +public class Deploy {} diff --git a/solr/core/src/java/org/apache/solr/cli/Install.java b/solr/core/src/java/org/apache/solr/cli/Install.java index 02e65fde9d7a..d4bbf978e9e8 100644 --- a/solr/core/src/java/org/apache/solr/cli/Install.java +++ b/solr/core/src/java/org/apache/solr/cli/Install.java @@ -17,5 +17,4 @@ package org.apache.solr.cli; -public class Install { -} +public class Install {} diff --git a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java index 18bff1b4ce4b..fcf1542e647b 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java +++ b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java @@ -17,5 +17,4 @@ package org.apache.solr.cli; -public class ListAvailable { -} +public class ListAvailable {} diff --git a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java index bbaf00dd85be..d50e1bbddf22 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java +++ b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java @@ -17,5 +17,4 @@ package org.apache.solr.cli; -public class ListDeployed { -} +public class ListDeployed {} diff --git a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java index b99b403d7f30..e0799cfd8907 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java +++ b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java @@ -17,5 +17,4 @@ package org.apache.solr.cli; -public class ListInstalled { -} +public class ListInstalled {} 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 246dedadd972..1f38478044bc 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -59,9 +59,7 @@ "1:Operation failed; check output for details." }, footerHeading = "%nExamples:%n", - subcommands = { - AddRepo.class - }, + subcommands = {AddRepo.class}, footer = { " # Add a package repository", " bin/solr package add-repo myrepo https://my.repo.example/repo", diff --git a/solr/core/src/java/org/apache/solr/cli/Undeploy.java b/solr/core/src/java/org/apache/solr/cli/Undeploy.java index c9dba5324547..286509ad9d34 100644 --- a/solr/core/src/java/org/apache/solr/cli/Undeploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Undeploy.java @@ -17,5 +17,4 @@ package org.apache.solr.cli; -public class Undeploy { -} +public class Undeploy {} diff --git a/solr/core/src/java/org/apache/solr/cli/Uninstall.java b/solr/core/src/java/org/apache/solr/cli/Uninstall.java index f857e2020670..c802acee7495 100644 --- a/solr/core/src/java/org/apache/solr/cli/Uninstall.java +++ b/solr/core/src/java/org/apache/solr/cli/Uninstall.java @@ -17,5 +17,4 @@ package org.apache.solr.cli; -public class Uninstall { -} +public class Uninstall {} diff --git a/solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java b/solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java index 70d0ccc7ccb2..b850ee70cf19 100644 --- a/solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java +++ b/solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java @@ -19,9 +19,7 @@ import picocli.CommandLine; -/** - * Runs all {@link PackageToolTest} tests through the picocli invocation path. - */ +/** Runs all {@link PackageToolTest} tests through the picocli invocation path. */ public class PackageToolPicocliTest extends PackageToolTest { @Override diff --git a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java index abb8be0f7a52..557ea5d1d345 100644 --- a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java +++ b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java @@ -373,14 +373,14 @@ public void testDeployValidationMessages() throws Exception { // package lookup should fail. runTool( new String[] { - "--solr-url", - solrUrl, - "deploy", - "NONEXISTENT_PKG", - "--collections", - "validation-test", - "--credentials", - SecurityJson.USER_PASS + "--solr-url", + solrUrl, + "deploy", + "NONEXISTENT_PKG", + "--collections", + "validation-test", + "--credentials", + SecurityJson.USER_PASS }, captureRuntime); String deployOut = captureRuntime.getOutput(); @@ -395,14 +395,14 @@ public void testDeployValidationMessages() throws Exception { // Undeploy of a package that was never deployed should give a clear message. runTool( new String[] { - "--solr-url", - solrUrl, - "undeploy", - "NONEXISTENT_PKG", - "--collections", - "validation-test", - "--credentials", - SecurityJson.USER_PASS + "--solr-url", + solrUrl, + "undeploy", + "NONEXISTENT_PKG", + "--collections", + "validation-test", + "--credentials", + SecurityJson.USER_PASS }, captureRuntime); String undeployOut = captureRuntime.getOutput(); From 9056c86190f23846971a6d6ed8e716e26c7ae685 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Thu, 17 Sep 2026 23:03:31 +0530 Subject: [PATCH 13/23] merge conflict resolved --- .../java/org/apache/solr/cli/PackageTool.java | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) 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 21b13610a233..f054cb300000 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -380,25 +380,18 @@ private void uninstall(String packageNameAndVersion) throws Exception { throw new SolrException( ErrorCode.BAD_REQUEST, "Package name and version are both required. Actual: " + packageNameAndVersion); - } catch (Exception exception) { - // We need to print this since SolrCLI drops the stack trace in favour - // of brevity. Package tool should surely print the full stacktrace! - exception.printStackTrace(); - throw exception; - } finally { - // Restore the old logging level - Configurator.setRootLevel(oldLevel); } + packageManager.uninstall(parsedVersion.first(), parsedVersion.second()); } private void handleCommand(String command, String[] cmdArgs, PackageFlags packageFlags) throws Exception { switch (command) { case "add-repo": - addRepo(cli.getArgs()[1], cli.getArgs()[2]); + addRepo(cmdArgs[0], cmdArgs[1]); break; case "add-key": - addKey(Path.of(cli.getArgs()[1])); + addKey(Path.of(cmdArgs[0])); break; case "list-installed": listInstalled(); @@ -407,47 +400,46 @@ private void handleCommand(String command, String[] cmdArgs, PackageFlags packag listAvailable(); break; case "list-deployed": - if (cli.hasOption(COLLECTION_OPTION)) { - listPackagesDeployedOnCollection(cli.getOptionValue(COLLECTION_OPTION)); + if (packageFlags.collection() != null) { + listPackagesDeployedOnCollection(packageFlags.collection()); } else { - // nuance that we use an arg here instead of requiring a --package parameter with a - // value in this code path - listCollectionsWithPackageDeployed(cli.getArgs()[1]); + listCollectionsWithPackageDeployed(cmdArgs[0]); } break; case "install": - install(cli.getArgList().get(1)); + install(cmdArgs[0]); break; case "deploy": - if (cli.hasOption(CLUSTER_OPTION) || cli.hasOption(COLLECTIONS_OPTION)) { + if (packageFlags.cluster() || packageFlags.collections() != null) { deploy( - cli.getArgList().get(1), - cli.hasOption(CLUSTER_OPTION), - cli.getOptionValue(COLLECTIONS_OPTION), - cli.getOptionValues(PARAM_OPTION), - cli.hasOption(UPDATE_OPTION), - cli.hasOption(NO_PROMPT_OPTION)); + cmdArgs[0], + packageFlags.cluster(), + collections, + packageFlags.parameters(), + packageFlags.update(), + packageFlags.noPrompt()); } else { printRed( "Either specify --cluster to deploy cluster level plugins or --collections to deploy collection level plugins"); } break; case "undeploy": - if (cli.hasOption(CLUSTER_OPTION) || cli.hasOption(COLLECTIONS_OPTION)) { + if (packageFlags.cluster() || packageFlags.collections() != null) { undeploy( - cli.getArgList().get(1), - cli.hasOption(CLUSTER_OPTION), - cli.getOptionValue(COLLECTIONS_OPTION)); + cmdArgs[0], + packageFlags.cluster(), + collections); } else { printRed( "Either specify --cluster to undeploy cluster level plugins or -collections to undeploy collection level plugins"); } break; case "uninstall": - uninstall(cli.getArgList().get(1)); + uninstall(cmdArgs[0]); break; default: throw new RuntimeException("Unrecognized command: " + cmd); + } } @Override From 1da69173ffcc23be8a722d00ff4e4d9c4dd10bc2 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 12:52:13 +0530 Subject: [PATCH 14/23] some changes done --- .../src/java/org/apache/solr/cli/AddRepo.java | 92 +------ .../apache/solr/cli/ConnectionOptions.java | 54 ++++ .../apache/solr/cli/PackageSubCommand.java | 66 +++++ .../java/org/apache/solr/cli/PackageTool.java | 256 +++++++----------- 4 files changed, 229 insertions(+), 239 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java diff --git a/solr/core/src/java/org/apache/solr/cli/AddRepo.java b/solr/core/src/java/org/apache/solr/cli/AddRepo.java index c1825323e809..61f46d7c2aec 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddRepo.java +++ b/solr/core/src/java/org/apache/solr/cli/AddRepo.java @@ -17,110 +17,36 @@ package org.apache.solr.cli; -import static org.apache.solr.cli.SolrCLI.printGreen; -import static org.apache.solr.packagemanager.PackageUtils.format; -import static org.apache.solr.packagemanager.PackageUtils.formatGreen; - -import org.apache.commons.cli.CommandLine; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configurator; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.common.SolrException; -import org.apache.solr.packagemanager.PackageManager; -import org.apache.solr.packagemanager.RepositoryManager; - /** Supports package add-repo command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "add-repo", description = "Add a package repository to Solr.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, footerHeading = "%nExamples:%n", footer = { " # Add a package repository", " bin/solr package add-repo myrepo https://my.repo.example/repo", }) -public class AddRepo extends ToolBase { - - @picocli.CommandLine.ParentCommand private PackageTool packageTool; - - @picocli.CommandLine.Mixin private HelpMixin helpMixin; - @picocli.CommandLine.Mixin private CredentialsOptions credentialsOptions; - - @picocli.CommandLine.ArgGroup private ConnectionOptions connectionOptions; +public class AddRepo extends PackageSubCommand { - @picocli.CommandLine.Parameters(index = "0", arity = "1", paramLabel = "REPOSITORY-NAME") + @picocli.CommandLine.Parameters(index = "0", arity = "1", paramLabel = "REPOSITORY-NAME", description = "Name of the package repository.") private String repoName; - @picocli.CommandLine.Parameters(index = "1", arity = "1", paramLabel = "REPOSITORY-URL") + @picocli.CommandLine.Parameters(index = "1", arity = "1", paramLabel = "REPOSITORY-URL", description = "URL of the package repository.") private String repoUrl; - public AddRepo() { - this(new DefaultToolRuntime()); - } - - public AddRepo(ToolRuntime runtime) { - super(runtime); - } - - @Override - public void runImpl(CommandLine cli) throws Exception { - throw new UnsupportedOperationException( - "add-repo is implemented via the commons-cli path under PackageTool"); - } - @Override public int callTool() throws Exception { - String credentials = credentialsOptions.credentials; - String solrUrl = packageTool.resolveSolrUrl(credentials); - String zkHost = packageTool.resolveZkHost(solrUrl, credentials); - addRepo(solrUrl, zkHost, credentials, repoName, repoUrl); - return 0; + return } @Override public String getName() { return "add-repo"; } - - @Override - public String getHeader() { - StringBuilder sb = new StringBuilder(); - format(sb, "Package Manager\n---------------"); - formatGreen(sb, "bin/solr package add-repo "); - format(sb, "Add a repository to Solr."); - format(sb, ""); - return sb.toString(); - } - - private void addRepo( - String solrUrl, String zkHost, String credentials, String repoName, String repoUrl) - throws Exception { - Level oldLevel = LoggerContext.getContext(false).getRootLogger().getLevel(); - Configurator.setRootLevel(Level.OFF); - - try { - if (zkHost == null) { - throw new SolrException( - SolrException.ErrorCode.INVALID_STATE, "Package manager only runs in SolrCloud"); - } - - try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials, true)) { - PackageManager packageManager = - new PackageManager(packageTool.getRuntime(), solrClient, solrUrl, zkHost); - try { - RepositoryManager repositoryManager = new RepositoryManager(solrClient, packageManager); - repositoryManager.addRepository(repoName, repoUrl); - printGreen("Added repository: " + repoName); - } finally { - packageManager.close(); - } - } - } catch (Exception exception) { - exception.printStackTrace(System.err); - throw exception; - } finally { - Configurator.setRootLevel(oldLevel); - } - } } diff --git a/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java b/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java index 0a782b5a60fb..3dd91e396cca 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java +++ b/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java @@ -17,7 +17,10 @@ package org.apache.solr.cli; import java.io.IOException; +import java.util.Map; +import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.common.util.EnvUtils; import picocli.CommandLine; /** @@ -73,4 +76,55 @@ String effectiveSolrUrl() throws IOException { } return solrUrl; } + + String resolveSolrUrl(String credentials) throws Exception { + if (connectionOptions != null) { + String solrUrl = connectionOptions.effectiveSolrUrl(); + if (solrUrl != null) { + return CLIUtils.normalizeSolrUrl(solrUrl); + } + String zkHost = connectionOptions.effectiveZkHost(); + if (zkHost != null) { + return CLIUtils.solrUrlFromConnection( + CloudSolrClient.CloudSolrClientConnection.parse(zkHost), credentials); + } + } + String zkHostProp = EnvUtils.getProperty("zkHost"); + if (zkHostProp != null && !zkHostProp.isBlank()) { + return CLIUtils.solrUrlFromConnection( + CloudSolrClient.CloudSolrClientConnection.parse(zkHostProp), credentials); + } + String defaultUrl = CLIUtils.getDefaultSolrUrl(); + CLIO.err( + "Neither --solr-connection, --zk-host or --solr-url parameters, nor SOLR_CONNECTION, ZK_HOST env var provided, so assuming solr url is " + + defaultUrl + + "."); + return defaultUrl; + } + + String resolveZkHost(String solrUrl, String credentials) throws Exception { + if (connectionOptions != null) { + String zkHost = connectionOptions.effectiveZkHost(); + if (zkHost != null) { + return zkHost; + } + } + String zkHostProp = EnvUtils.getProperty("zkHost"); + if (zkHostProp != null && !zkHostProp.isBlank()) { + return zkHostProp; + } + try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials)) { + Map status = StatusTool.reportStatus(solrClient); + @SuppressWarnings("unchecked") + Map cloud = (Map) status.get("cloud"); + if (cloud != null) { + String zookeeper = cloud.get("ZooKeeper").toString(); + if (zookeeper != null && zookeeper.endsWith("(embedded)")) { + zookeeper = zookeeper.substring(0, zookeeper.length() - "(embedded)".length()); + } + return zookeeper; + } + } + return null; + } } diff --git a/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java new file mode 100644 index 000000000000..7454a33b08bb --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package org.apache.solr.cli; + +import org.apache.commons.cli.CommandLine; +import org.apache.solr.packagemanager.PackageManager; +import org.apache.solr.packagemanager.RepositoryManager; + +/** Shared picocli wiring for {@code bin/solr package leaves} */ +abstract class PackageSubCommand extends ToolBase { + + @FunctionalInterface + interface PackageAction { + void run(PackageManager packageManager, RepositoryManager repositoryManager) throws Exception; + } + + @picocli.CommandLine.ParentCommand PackageTool packageTool; + + @picocli.CommandLine.Mixin CredentialsOptions credentialsOptions; + + @picocli.CommandLine.ArgGroup(exclusive = true, multiplicity = "0..1") + + ConnectionOptions connectionOptions; + + PackageSubCommand() { + super(new DefaultToolRuntime()); + } + + @Override + public void runImpl(CommandLine cli) throws Exception { + throw new UnsupportedOperationException( + getName() + " is implemented via the commons-cli path under PackageTool" + ); + } + + final int runWithManagers(PackageAction action) throws Exception { + String credentials = + credentialsOptions.credentials != null + ? credentialsOptions.credentials + : packageTool.credentialOptions != null + ? packageTool.credentialOptions.credentials + : null; + + packageTool.runWithManagers( + connectionOptions != null ? connectionOptions : packageTool.connectionOptions, + credentials, + action + ); + return 0; + } +} 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 f054cb300000..4480e89e677c 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -32,13 +32,11 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configurator; -import org.apache.lucene.util.SuppressForbidden; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; -import org.apache.solr.common.util.EnvUtils; import org.apache.solr.common.util.Pair; +import org.apache.solr.common.util.SuppressForbidden; import org.apache.solr.packagemanager.PackageManager; import org.apache.solr.packagemanager.PackageUtils; import org.apache.solr.packagemanager.RepositoryManager; @@ -52,14 +50,24 @@ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "package", - description = "Sub commands to Install, deploy and manage Solr packages in SolrCloud.", + description = "", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { "0:Operation completed successfully.", "1:Operation failed; check output for details." }, footerHeading = "%nExamples:%n", - subcommands = {AddRepo.class}, + subcommands = { + AddRepo.class, + AddKey.class, + ListInstalled.class, + ListAvailable.class, + ListDeployed.class, + Install.class, + Deploy.class, + Undeploy.class, + Uninstall.class + }, footer = { " # Add a package repository", " bin/solr package add-repo myrepo https://my.repo.example/repo", @@ -118,6 +126,7 @@ public class PackageTool extends ToolBase { .desc("Don't prompt for input; accept all default choices, defaults to false.") .get(); + /** Parameters for package sub-commands, independent of the command line parser */ record PackageFlags( String collections, boolean cluster, @@ -126,64 +135,15 @@ record PackageFlags( String collection, boolean noPrompt) {} - // --- picocli fields --- + @picocli.CommandLine.ArgGroup(exclusive = true, multiplicity = "0..1") + ConnectionOptions connectionOptions; + + @picocli.CommandLine.Mixin CredentialsOptions credentialsOptions; - @picocli.CommandLine.Mixin private HelpMixin helpMixin; + @picocli.CommandLine.Spec private picocli.CommandLine.Model.CommandSpec spec; - @picocli.CommandLine.ArgGroup(exclusive = true, multiplicity = "0..1") - private ConnectionOptions connectionOptions; - - @picocli.CommandLine.Mixin private CredentialsOptions credentialsOptions; - - @picocli.CommandLine.Parameters( - index = "0", - arity = "1", - paramLabel = "COMMAND", - description = - "Package command: add-repo, add-key, list-installed, list-available, list-deployed, install, deploy, undeploy, uninstall.") - private String cmd; - - @picocli.CommandLine.Parameters( - index = "1..*", - arity = "0..*", - paramLabel = "ARGS", - description = - "Command-specific arguments (package name[:version], repository name/URL, key file, etc.).") - private String[] cmdArgs; - - @picocli.CommandLine.Option( - names = {"--collections"}, - paramLabel = "COLLECTIONS", - description = - "Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins.") - private String collections; - - @picocli.CommandLine.Option( - names = {"--cluster"}, - description = "Specifies that this action should affect cluster-level plugins only.") - private boolean cluster; - - @picocli.CommandLine.Option( - names = {"--param"}, - paramLabel = "PARAMS", - description = "List of parameters to be used with the deploy command.") - private String[] param; - - @picocli.CommandLine.Option( - names = {"--update"}, - description = "If a deployment is an update over a previous deployment.") - private boolean update; - - @picocli.CommandLine.Option( - names = {"-c", "--collection"}, - paramLabel = "COLLECTION", - description = "The collection to apply the package to.") - private String collection; - - @picocli.CommandLine.Option( - names = {"-y", "--no-prompt"}, - description = "Don't prompt for input; accept all default choices, defaults to false.") - private boolean noPrompt; + private PackageManager packageManager; + private RepositoryManager repositoryManager; public PackageTool() { this(new DefaultToolRuntime()); @@ -198,19 +158,9 @@ public String getName() { return "package"; } - public PackageManager packageManager; - public RepositoryManager repositoryManager; @Override - @SuppressForbidden( - reason = - "We really need to print the stacktrace here, otherwise " - + "there shall be little else information to debug problems. Other SolrCLI tools " - + "don't print stack traces, hence special treatment is needed here." - + "Need to turn off logging, and SLF4J doesn't seem to provide for a way.") public void runImpl(CommandLine cli) throws Exception { - String solrUrl = CLIUtils.normalizeSolrUrl(cli); - String zkHost = CLIUtils.getZkHost(cli); String credentials = cli.getOptionValue(CommonCLIOptions.CREDENTIALS_OPTION); String command = cli.getArgs()[0]; String[] cmdArgs = Arrays.copyOfRange(cli.getArgs(), 1, cli.getArgs().length); @@ -223,12 +173,12 @@ public void runImpl(CommandLine cli) throws Exception { cli.getOptionValue(COLLECTION_OPTION), cli.hasOption(NO_PROMPT_OPTION)); - executePackage(solrUrl, zkHost, credentials, command, cmdArgs, packageFlags); + executePackage(cli, credentials, command, cmdArgs, packageFlags); } + @SuppressForbidden(reason = "TBA") private void executePackage( - String solrUrl, - String zkHost, + CommandLine cli, String credentials, String command, String[] cmdArgs, @@ -240,6 +190,9 @@ private void executePackage( Configurator.setRootLevel(Level.OFF); try { + String solrUrl = CLIUtils.normalizeSolrUrl(cli); + String zkHost = CLIUtils.getZkHost(cli); + if (zkHost == null) { throw new SolrException(ErrorCode.INVALID_STATE, "Package manager runs only in SolrCloud"); } @@ -255,7 +208,7 @@ private void executePackage( packageManager.close(); } } - log.info("Finished: {}", cmd); + log.info("Finished: {}", command); } catch (Exception ex) { // We need to print this since SolrCLI drops the stack trace in favour @@ -268,23 +221,65 @@ private void executePackage( } } - private void addRepo(String repoName, String repoUrl) throws Exception { + /** + * Picocli subcommand path: resolve connection, open managers, run action, close. + * Commons-cli runs through {@link #executePackage(CommandLine, String, String, String[], PackageFlags)} instead. + */ + @SuppressForbidden( + reason = + "TBA") + void runWithManagers( + ConnectionOptions opts, String credentials, PackageSubCommand.PackageAction action) + throws Exception { + // Need a logging free, clean output going through to the user. + Level oldLevel = LoggerContext.getContext(false).getRootLogger().getLevel(); + Configurator.setRootLevel(Level.OFF); + + try { + String solrUrl = ConnectionOptions.resolveSolrUrl(opts, credentials); + String zkHost = ConnectionOptions.resolveZkHost(opts, solrUrl, credentials); + + if (zkHost == null) { + throw new SolrException(ErrorCode.INVALID_STATE, "Package manager runs only in SolrCloud"); + } + + log.info("ZK: {}", zkHost); + + try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials, true)) { + packageManager = new PackageManager(runtime, solrClient, solrUrl, zkHost); + try { + repositoryManager = new RepositoryManager(solrClient, packageManager); + action.run(packageManager, repositoryManager); + } finally { + packageManager.close(); + } + } + + } catch (Exception ex) { + ex.printStackTrace(); + throw ex; + } finally { + Configurator.setRootLevel(oldLevel); + } + } + + void addRepo(RepositoryManager repositoryManager, String repoName, String repoUrl) throws Exception { repositoryManager.addRepository(repoName, repoUrl); printGreen("Added repository: " + repoName); } - private void addKey(Path keyFile) throws Exception { + void addKey(RepositoryManager repositoryManager, Path keyFile) throws Exception { repositoryManager.addKey(Files.readAllBytes(keyFile), keyFile.getFileName().toString()); } - private void listInstalled() throws Exception { + void listInstalled(PackageManager packageManager) throws Exception { printGreen("Installed packages:\n-----"); for (SolrPackageInstance pkg : packageManager.fetchInstalledPackageInstances()) { printGreen(pkg); } } - private void listAvailable() throws Exception { + void listAvailable(RepositoryManager repositoryManager) throws Exception { printGreen("Available packages:\n-----"); for (SolrPackage pkg : repositoryManager.getPackages()) { printGreen(pkg.name + " \t\t" + pkg.description); @@ -294,7 +289,7 @@ private void listAvailable() throws Exception { } } - private void listPackagesDeployedOnCollection(String collection) { + void listPackagesDeployedOnCollection(PackageManager packageManager, String collection) { Map packages = packageManager.getPackagesDeployed(collection); printGreen("Packages deployed on " + collection + ":"); for (String packageName : packages.keySet()) { @@ -302,7 +297,7 @@ private void listPackagesDeployedOnCollection(String collection) { } } - private void listCollectionsWithPackageDeployed(String packageName) { + void listCollectionsWithPackageDeployed(PackageManager packageManager, String packageName) { Map deployedCollections = packageManager.getDeployedCollections(packageName); if (!deployedCollections.isEmpty()) { printGreen("Collections on which package " + packageName + " was deployed:"); @@ -321,7 +316,8 @@ private void listCollectionsWithPackageDeployed(String packageName) { } } - private void install(String packageNameAndVersion) throws Exception { + void install(RepositoryManager repositoryManager, String packageNameAndVersion) + throws Exception { Pair parsedVersion = parsePackageVersion(packageNameAndVersion); String packageName = parsedVersion.first(); String version = parsedVersion.second(); @@ -336,7 +332,8 @@ private void install(String packageNameAndVersion) throws Exception { /** * @param collections raw comma-separated value of the --collections option, or null */ - private void deploy( + void deploy( + PackageManager packageManager, String packageNameAndVersion, boolean cluster, String collections, @@ -358,7 +355,11 @@ private void deploy( /** * @param collections raw comma-separated value of the --collections option, or null */ - private void undeploy(String packageNameAndVersion, boolean cluster, String collections) + void undeploy( + PackageManager packageManager, + String packageNameAndVersion, + boolean cluster, + String collections) throws Exception { Pair parsedVersion = parsePackageVersion(packageNameAndVersion); if (parsedVersion.second() != null) { @@ -374,7 +375,8 @@ private void undeploy(String packageNameAndVersion, boolean cluster, String coll packageManager.undeploy(packageName, collectionArray, cluster); } - private void uninstall(String packageNameAndVersion) throws Exception { + void uninstall(PackageManager packageManager, String packageNameAndVersion) + throws Exception { Pair parsedVersion = parsePackageVersion(packageNameAndVersion); if (parsedVersion.second() == null) { throw new SolrException( @@ -388,33 +390,34 @@ private void handleCommand(String command, String[] cmdArgs, PackageFlags packag throws Exception { switch (command) { case "add-repo": - addRepo(cmdArgs[0], cmdArgs[1]); + addRepo(repositoryManager, cmdArgs[0], cmdArgs[1]); break; case "add-key": - addKey(Path.of(cmdArgs[0])); + addKey(repositoryManager, Path.of(cmdArgs[0])); break; case "list-installed": - listInstalled(); + listInstalled(packageManager); break; case "list-available": - listAvailable(); + listAvailable(repositoryManager); break; case "list-deployed": if (packageFlags.collection() != null) { - listPackagesDeployedOnCollection(packageFlags.collection()); + listPackagesDeployedOnCollection(packageManager, packageFlags.collection()); } else { - listCollectionsWithPackageDeployed(cmdArgs[0]); + listCollectionsWithPackageDeployed(packageManager, cmdArgs[0]); } break; case "install": - install(cmdArgs[0]); + install(repositoryManager, cmdArgs[0]); break; case "deploy": if (packageFlags.cluster() || packageFlags.collections() != null) { deploy( + packageManager, cmdArgs[0], packageFlags.cluster(), - collections, + packageFlags.collections(), packageFlags.parameters(), packageFlags.update(), packageFlags.noPrompt()); @@ -426,19 +429,17 @@ private void handleCommand(String command, String[] cmdArgs, PackageFlags packag case "undeploy": if (packageFlags.cluster() || packageFlags.collections() != null) { undeploy( - cmdArgs[0], - packageFlags.cluster(), - collections); + packageManager, cmdArgs[0], packageFlags.cluster(), packageFlags.collections()); } else { printRed( "Either specify --cluster to undeploy cluster level plugins or -collections to undeploy collection level plugins"); } break; case "uninstall": - uninstall(cmdArgs[0]); + uninstall(packageManager, cmdArgs[0]); break; default: - throw new RuntimeException("Unrecognized command: " + cmd); + throw new RuntimeException("Unrecognized command: " + command); } } @@ -531,64 +532,7 @@ public Options getOptions() { @Override public int callTool() throws Exception { - String credentials = credentialsOptions.credentials; - String solrUrl = resolveSolrUrl(credentials); - String zkHost = resolveZkHost(solrUrl, credentials); - String[] args = cmdArgs == null ? new String[0] : cmdArgs; - PackageFlags packageFlags = - new PackageFlags(collections, cluster, param, update, collection, noPrompt); - executePackage(solrUrl, zkHost, credentials, cmd, args, packageFlags); + spec.commandLine().usage(CLIO.getOutStream()); return 0; } - - String resolveSolrUrl(String credentials) throws Exception { - if (connectionOptions != null) { - String solrUrl = connectionOptions.effectiveSolrUrl(); - if (solrUrl != null) { - return CLIUtils.normalizeSolrUrl(solrUrl); - } - String zkHost = connectionOptions.effectiveZkHost(); - if (zkHost != null) { - return CLIUtils.solrUrlFromConnection( - CloudSolrClient.CloudSolrClientConnection.parse(zkHost), credentials); - } - } - String zkHostProp = EnvUtils.getProperty("zkHost"); - if (zkHostProp != null && !zkHostProp.isBlank()) { - return CLIUtils.solrUrlFromConnection( - CloudSolrClient.CloudSolrClientConnection.parse(zkHostProp), credentials); - } - String defaultUrl = CLIUtils.getDefaultSolrUrl(); - CLIO.err( - "Neither --solr-connection, --zk-host or --solr-url parameters, nor SOLR_CONNECTION, ZK_HOST env var provided, so assuming solr url is " - + defaultUrl - + "."); - return defaultUrl; - } - - String resolveZkHost(String solrUrl, String credentials) throws Exception { - if (connectionOptions != null) { - String zkHost = connectionOptions.effectiveZkHost(); - if (zkHost != null) { - return zkHost; - } - } - String zkHostProp = EnvUtils.getProperty("zkHost"); - if (zkHostProp != null && !zkHostProp.isBlank()) { - return zkHostProp; - } - try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials)) { - Map status = StatusTool.reportStatus(solrClient); - @SuppressWarnings("unchecked") - Map cloud = (Map) status.get("cloud"); - if (cloud != null) { - String zookeeper = cloud.get("ZooKeeper").toString(); - if (zookeeper != null && zookeeper.endsWith("(embedded)")) { - zookeeper = zookeeper.substring(0, zookeeper.length() - "(embedded)".length()); - } - return zookeeper; - } - } - return null; - } } From 638f0979e2ae44dc10c602c90ef40293c1dc1349 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 14:19:02 +0530 Subject: [PATCH 15/23] subcommands ready --- .../src/java/org/apache/solr/cli/AddKey.java | 37 ++++++++- .../src/java/org/apache/solr/cli/AddRepo.java | 14 +++- .../apache/solr/cli/ConnectionOptions.java | 26 ++++++- .../src/java/org/apache/solr/cli/Deploy.java | 76 ++++++++++++++++++- .../src/java/org/apache/solr/cli/Install.java | 40 +++++++++- .../org/apache/solr/cli/ListAvailable.java | 28 ++++++- .../org/apache/solr/cli/ListDeployed.java | 59 +++++++++++++- .../org/apache/solr/cli/ListInstalled.java | 28 ++++++- .../java/org/apache/solr/cli/PackageTool.java | 3 +- .../java/org/apache/solr/cli/Undeploy.java | 54 ++++++++++++- .../java/org/apache/solr/cli/Uninstall.java | 36 ++++++++- 11 files changed, 387 insertions(+), 14 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/AddKey.java b/solr/core/src/java/org/apache/solr/cli/AddKey.java index 1d50ac39fd5c..167c4295a5c8 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddKey.java +++ b/solr/core/src/java/org/apache/solr/cli/AddKey.java @@ -17,4 +17,39 @@ package org.apache.solr.cli; -public class AddKey {} +import java.nio.file.Path; + +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "add-key", + description = "Add a trusted key to Solr.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # Add a trusted public key", + " bin/solr package add-key /path/to/public.key.der", + }) +public class AddKey extends PackageSubCommand { + + @picocli.CommandLine.Parameters( + index = "0", + arity = "1", + paramLabel = "KEY-FILE", + description = "Path to a file containing the trusted key.") + private Path keyFile; + + @Override + public int callTool() throws Exception { + return runWithManagers(((packageManager, repositoryManager) -> packageTool.addKey(repositoryManager, keyFile))); + } + + @Override + public String getName() { + return "add-key"; + } +} diff --git a/solr/core/src/java/org/apache/solr/cli/AddRepo.java b/solr/core/src/java/org/apache/solr/cli/AddRepo.java index 61f46d7c2aec..56fd05a31d34 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddRepo.java +++ b/solr/core/src/java/org/apache/solr/cli/AddRepo.java @@ -34,15 +34,23 @@ }) public class AddRepo extends PackageSubCommand { - @picocli.CommandLine.Parameters(index = "0", arity = "1", paramLabel = "REPOSITORY-NAME", description = "Name of the package repository.") + @picocli.CommandLine.Parameters( + index = "0", + arity = "1", + paramLabel = "REPOSITORY-NAME", + description = "Name of the package repository.") private String repoName; - @picocli.CommandLine.Parameters(index = "1", arity = "1", paramLabel = "REPOSITORY-URL", description = "URL of the package repository.") + @picocli.CommandLine.Parameters( + index = "1", + arity = "1", + paramLabel = "REPOSITORY-URL", + description = "URL of the package repository.") private String repoUrl; @Override public int callTool() throws Exception { - return + return runWithManagers(((packageManager, repositoryManager) -> packageTool.addRepo(repositoryManager, repoName, repoUrl))); } @Override diff --git a/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java b/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java index 3dd91e396cca..211776203345 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java +++ b/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java @@ -77,7 +77,7 @@ String effectiveSolrUrl() throws IOException { return solrUrl; } - String resolveSolrUrl(String credentials) throws Exception { + String resolveSolrUrl(ConnectionOptions connectionOptions, String credentials) throws Exception { if (connectionOptions != null) { String solrUrl = connectionOptions.effectiveSolrUrl(); if (solrUrl != null) { @@ -89,11 +89,22 @@ String resolveSolrUrl(String credentials) throws Exception { CloudSolrClient.CloudSolrClientConnection.parse(zkHost), credentials); } } + + String solrConnectionProp = EnvUtils.getProperty("solr-connection"); + if (solrConnectionProp != null && !solrConnectionProp.isBlank()) { + var connection = CloudSolrClient.CloudSolrClientConnection.parse(solrConnectionProp); + if (connection.isZookeeper()) { + return CLIUtils.solrUrlFromConnection(connection, credentials); + } + return CLIUtils.normalizeSolrUrl(connection.quorumItems().get(0)); + } + String zkHostProp = EnvUtils.getProperty("zkHost"); if (zkHostProp != null && !zkHostProp.isBlank()) { return CLIUtils.solrUrlFromConnection( CloudSolrClient.CloudSolrClientConnection.parse(zkHostProp), credentials); } + String defaultUrl = CLIUtils.getDefaultSolrUrl(); CLIO.err( "Neither --solr-connection, --zk-host or --solr-url parameters, nor SOLR_CONNECTION, ZK_HOST env var provided, so assuming solr url is " @@ -102,17 +113,28 @@ String resolveSolrUrl(String credentials) throws Exception { return defaultUrl; } - String resolveZkHost(String solrUrl, String credentials) throws Exception { + String resolveZkHost(ConnectionOptions connectionOptions, String solrUrl, String credentials) + throws Exception { if (connectionOptions != null) { String zkHost = connectionOptions.effectiveZkHost(); if (zkHost != null) { return zkHost; } } + + String solrConnectionProp = EnvUtils.getProperty("solr-connection"); + if (solrConnectionProp != null && !solrConnectionProp.isBlank()) { + var connection = CloudSolrClient.CloudSolrClientConnection.parse(solrConnectionProp); + if (connection.isZookeeper()) { + return solrConnectionProp; + } + } + String zkHostProp = EnvUtils.getProperty("zkHost"); if (zkHostProp != null && !zkHostProp.isBlank()) { return zkHostProp; } + try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials)) { Map status = StatusTool.reportStatus(solrClient); @SuppressWarnings("unchecked") diff --git a/solr/core/src/java/org/apache/solr/cli/Deploy.java b/solr/core/src/java/org/apache/solr/cli/Deploy.java index 7362226e7e1d..b3ff8f47acb5 100644 --- a/solr/core/src/java/org/apache/solr/cli/Deploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Deploy.java @@ -17,4 +17,78 @@ package org.apache.solr.cli; -public class Deploy {} +import java.nio.file.Path; + +import static org.apache.solr.cli.SolrCLI.printRed; + +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "deploy", + description = "Deploy an installed package to collections or at cluster level.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # Deploy a package to a collection", + " bin/solr package deploy mypkg:1.0.0 --collections myCollection -y", + "", + " # Update an existing deployment", + " bin/solr package deploy mypkg --update --collections myCollection -y" + }) +public class Deploy extends PackageSubCommand { + + @picocli.CommandLine.Parameters( + index = "0", + arity = "1", + paramLabel = "PACKAGE[:VERSION]", + description = "Package name, optionally with :version.") + private String packageNameAndVersion; + + @picocli.CommandLine.Option( + names = {"--cluster"}, + description = "Specifies that this action should affect cluster-level plugins only.") + private boolean cluster; + + @picocli.CommandLine.Option( + names = {"--collections"}, + paramLabel = "COLLECTIONS", + description = "Collections on which this package needs to be deployed on, excluding cluster level plugins") + private String collections; + + @picocli.CommandLine.Option( + names = {"-p", "--param"}, + paramLabel = "PARAMS", + description = "List of parameters to be used with the deploy command") + private String[] params; + + @picocli.CommandLine.Option( + names = {"--update"}, + description = "If a deployment is an update over a previous deployment.") + private boolean update; + + @picocli.CommandLine.Option( + names = {"-y", "--no-prompt"}, + description = "Do not prompt for input; accept all default choices, defaults to false.") + private boolean noPrompt; + + @Override + public int callTool() throws Exception { + if (!cluster && collections == null) { + printRed( + "Either specify --cluster to deploy cluster level plugins or --collections to deploy collection level plugins"); + return 1; + } + return runWithManagers( + (packageManager, repositoryManager) -> + packageTool.deploy(packageManager, packageNameAndVersion, cluster, collections, params, update, noPrompt)); + } + + @Override + public String getName() { + return "deploy"; + } +} diff --git a/solr/core/src/java/org/apache/solr/cli/Install.java b/solr/core/src/java/org/apache/solr/cli/Install.java index d4bbf978e9e8..289a6678c940 100644 --- a/solr/core/src/java/org/apache/solr/cli/Install.java +++ b/solr/core/src/java/org/apache/solr/cli/Install.java @@ -17,4 +17,42 @@ package org.apache.solr.cli; -public class Install {} +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "install", + description = "Install a package into Solr.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # Install a specific package version", + " bin/solr package install mypkg:1.0.0", + "", + " # Install the latest available version", + " bin/solr package install mypkg" + }) +public class Install extends PackageSubCommand { + + @picocli.CommandLine.Parameters( + index = "0", + arity = "1", + paramLabel = "PACKAGE[:VERSION]", + description = "Package name, optionally with :version.") + private String packageNameAndVersion; + + @Override + public int callTool() throws Exception { + final boolean[] status = {true}; + runWithManagers((packageManager, repositoryManager) -> status[0] = packageTool.install(repositoryManager, packageNameAndVersion)); + return status[0] ? 0 : 1; + } + + @Override + public String getName() { + return "install"; + } +} diff --git a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java index fcf1542e647b..02915e696b50 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java +++ b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java @@ -17,4 +17,30 @@ package org.apache.solr.cli; -public class ListAvailable {} +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "list-available", + description = "Print a list of packages available in the repositories.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # List packages available from configured repositories", + " bin/solr package list-available", + }) +public class ListAvailable extends PackageSubCommand { + + @Override + public int callTool() throws Exception { + return runWithManagers((packageManager, repositoryManager) -> packageTool.listAvailable(repositoryManager)); + } + + @Override + public String getName() { + return "list-available"; + } +} diff --git a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java index d50e1bbddf22..e269396b4255 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java +++ b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java @@ -17,4 +17,61 @@ package org.apache.solr.cli; -public class ListDeployed {} +import static org.apache.solr.cli.SolrCLI.printRed; + +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "list-deployed", + description = "Print packages deployed on a collection, or collections where a package is deployed.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # List packages deployed on a collection", + " bin/solr package list-deployed -c myCollection", + "", + " # List collections where a package is deployed", + " bin/solr package list-deployed mypkg" + }) +public class ListDeployed extends PackageSubCommand { + + @picocli.CommandLine.Option( + names = {"-c", "--collection"}, + paramLabel = "COLLECTION", + description = "Collection for which deployed packages are to be listed.") + private String collection; + + @picocli.CommandLine.Parameters( + index = "0", + arity = "0..1", + paramLabel = "PACKAGE", + description = "Package name; lists collections where this package is deployed.") + private String packageName; + + + @Override + public int callTool() throws Exception { + if (collection == null && packageName == null) { + printRed("Either -c/--collection or a package name is required."); + return 1; + } + + return runWithManagers( + (packageManager, repositoryManager) -> { + if (collection != null) { + packageTool.listPackagesDeployedOnCollection(packageManager, collection); + } else { + packageTool.listCollectionsWithPackageDeployed(packageManager, packageName); + } + }); + } + + @Override + public String getName() { + return "list-deployed"; + } +} diff --git a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java index e0799cfd8907..a85666cad62b 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java +++ b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java @@ -17,4 +17,30 @@ package org.apache.solr.cli; -public class ListInstalled {} +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "list-installed", + description = "Print a list of packages installed in Solr.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # List all installed packages", + " bin/solr package list-installed", + }) +public class ListInstalled extends PackageSubCommand { + + @Override + public int callTool() throws Exception { + return runWithManagers((packageManager, repositoryManager) -> packageTool.listInstalled(packageManager)); + } + + @Override + public String getName() { + return "list-installed"; + } +} 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 4480e89e677c..d63fa8af113c 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -316,7 +316,7 @@ void listCollectionsWithPackageDeployed(PackageManager packageManager, String pa } } - void install(RepositoryManager repositoryManager, String packageNameAndVersion) + boolean install(RepositoryManager repositoryManager, String packageNameAndVersion) throws Exception { Pair parsedVersion = parsePackageVersion(packageNameAndVersion); String packageName = parsedVersion.first(); @@ -327,6 +327,7 @@ void install(RepositoryManager repositoryManager, String packageNameAndVersion) } else { printRed(packageName + " installation failed."); } + return success; } /** diff --git a/solr/core/src/java/org/apache/solr/cli/Undeploy.java b/solr/core/src/java/org/apache/solr/cli/Undeploy.java index 286509ad9d34..462a11a6f2b6 100644 --- a/solr/core/src/java/org/apache/solr/cli/Undeploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Undeploy.java @@ -17,4 +17,56 @@ package org.apache.solr.cli; -public class Undeploy {} +import static org.apache.solr.cli.SolrCLI.printRed; + +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "undeploy", + description = "Undeploy a package from specified collection(s) or at cluster level.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # Undeploy a package from a collection", + " bin/solr package undeploy mypkg --collections myCollection" + }) +public class Undeploy extends PackageSubCommand { + + @picocli.CommandLine.Parameters( + index = "0", + arity = "1", + paramLabel = "PACKAGE", + description = "Package name") + private String packageName; + + @picocli.CommandLine.Option( + names = {"--cluster"}, + description = "Specifies that this action should affect cluster-level plugins only.") + private boolean cluster; + + @picocli.CommandLine.Option( + names = {"--collections"}, + paramLabel = "COLLECTIONS", + description = "Collections on which this package needs to be undeployed from, excluding cluster level plugins") + private String collections; + + @Override + public int callTool() throws Exception { + if (!cluster && collections == null) { + printRed( + "Either specify --cluster to undeploy cluster level plugins or --collections to undeploy collection level plugins"); + return 1; + } + return runWithManagers( + (packageManager, repositoryManager) -> packageTool.undeploy(packageManager, packageName, cluster, collections)); + } + + @Override + public String getName() { + return "undeploy"; + } +} diff --git a/solr/core/src/java/org/apache/solr/cli/Uninstall.java b/solr/core/src/java/org/apache/solr/cli/Uninstall.java index c802acee7495..bdbd5517b242 100644 --- a/solr/core/src/java/org/apache/solr/cli/Uninstall.java +++ b/solr/core/src/java/org/apache/solr/cli/Uninstall.java @@ -17,4 +17,38 @@ package org.apache.solr.cli; -public class Uninstall {} +/** Supports package add-repo command in the bin/solr script. */ +@SuppressWarnings("UnnecessarilyFullyQualified") +@picocli.CommandLine.Command( + name = "uninstall", + description = + "Uninstall any package with a specified version from Solr.", + exitCodeListHeading = "%nExit Codes:%n", + exitCodeList = { + "0: Operation completed successfully.", + "1: Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + footer = { + " # Uninstall a specific package version", + " bin/solr package uninstall mypkg:1.0.0", + }) +public class Uninstall extends PackageSubCommand { + + @picocli.CommandLine.Parameters( + index = "0", + arity = "1", + paramLabel = "PACKAGE:VERSION", + description = "Package name and version, separated by a colon.") + private String packageNameAndVersion; + + @Override + public int callTool() throws Exception { + return runWithManagers((packageManager, repositoryManager) -> packageTool.uninstall(packageManager, packageNameAndVersion)); + } + + @Override + public String getName() { + return "uninstall"; + } +} From 1e8bb7027346cdd04f55177d16a00a36ca2d1a6f Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 14:30:17 +0530 Subject: [PATCH 16/23] generated cli docs --- .../apache/solr/cli/ConnectionOptions.java | 4 +- .../apache/solr/cli/PackageSubCommand.java | 4 +- .../deployment-guide/deployment-nav.adoc | 10 ++ .../deployment-guide/pages/cli/index.adoc | 10 ++ .../pages/cli/solr-package-add-key.adoc | 96 +++++++++++++++ .../pages/cli/solr-package-add-repo.adoc | 100 +++++++++++++++ .../pages/cli/solr-package-deploy.adoc | 116 ++++++++++++++++++ .../pages/cli/solr-package-install.adoc | 100 +++++++++++++++ .../cli/solr-package-list-available.adoc | 88 +++++++++++++ .../pages/cli/solr-package-list-deployed.adoc | 104 ++++++++++++++++ .../cli/solr-package-list-installed.adoc | 88 +++++++++++++ .../pages/cli/solr-package-undeploy.adoc | 103 ++++++++++++++++ .../pages/cli/solr-package-uninstall.adoc | 96 +++++++++++++++ .../pages/cli/solr-package.adoc | 79 ++++++------ 14 files changed, 954 insertions(+), 44 deletions(-) create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-add-key.adoc create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-add-repo.adoc create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-deploy.adoc create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-install.adoc create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-available.adoc create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-deployed.adoc create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-installed.adoc create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-undeploy.adoc create mode 100644 solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-uninstall.adoc diff --git a/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java b/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java index 211776203345..db7305647aa2 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java +++ b/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java @@ -77,7 +77,7 @@ String effectiveSolrUrl() throws IOException { return solrUrl; } - String resolveSolrUrl(ConnectionOptions connectionOptions, String credentials) throws Exception { + static String resolveSolrUrl(ConnectionOptions connectionOptions, String credentials) throws Exception { if (connectionOptions != null) { String solrUrl = connectionOptions.effectiveSolrUrl(); if (solrUrl != null) { @@ -113,7 +113,7 @@ String resolveSolrUrl(ConnectionOptions connectionOptions, String credentials) t return defaultUrl; } - String resolveZkHost(ConnectionOptions connectionOptions, String solrUrl, String credentials) + static String resolveZkHost(ConnectionOptions connectionOptions, String solrUrl, String credentials) throws Exception { if (connectionOptions != null) { String zkHost = connectionOptions.effectiveZkHost(); diff --git a/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java index 7454a33b08bb..169f3011f514 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java @@ -52,8 +52,8 @@ final int runWithManagers(PackageAction action) throws Exception { String credentials = credentialsOptions.credentials != null ? credentialsOptions.credentials - : packageTool.credentialOptions != null - ? packageTool.credentialOptions.credentials + : packageTool.credentialsOptions != null + ? packageTool.credentialsOptions.credentials : null; packageTool.runWithManagers( diff --git a/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc b/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc index 93cab57d17cf..5708b61b83bc 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc @@ -23,6 +23,16 @@ *** xref:cli/solr-auth.adoc[auth] *** xref:cli/solr-create.adoc[create] *** xref:cli/solr-delete.adoc[delete] +*** xref:cli/solr-package.adoc[package] +**** xref:cli/solr-package-add-key.adoc[key] +**** xref:cli/solr-package-add-repo.adoc[repo] +**** xref:cli/solr-package-deploy.adoc[deploy] +**** xref:cli/solr-package-install.adoc[install] +**** xref:cli/solr-package-list-available.adoc[available] +**** xref:cli/solr-package-list-deployed.adoc[deployed] +**** xref:cli/solr-package-list-installed.adoc[installed] +**** xref:cli/solr-package-undeploy.adoc[undeploy] +**** xref:cli/solr-package-uninstall.adoc[uninstall] *** xref:cli/solr-start.adoc[start] *** xref:cli/solr-status.adoc[status] *** xref:cli/solr-stop.adoc[stop] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/index.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/index.adoc index f00109598068..4442410513d1 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/index.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/index.adoc @@ -62,6 +62,16 @@ Any command not listed here is unavailable when the picocli implementation is en |xref:cli/solr-auth.adoc[bin/solr auth] |xref:cli/solr-create.adoc[bin/solr create] |xref:cli/solr-delete.adoc[bin/solr delete] +|xref:cli/solr-package-add-key.adoc[bin/solr package add key] +|xref:cli/solr-package-add-repo.adoc[bin/solr package add repo] +|xref:cli/solr-package-deploy.adoc[bin/solr package deploy] +|xref:cli/solr-package-install.adoc[bin/solr package install] +|xref:cli/solr-package-list-available.adoc[bin/solr package list available] +|xref:cli/solr-package-list-deployed.adoc[bin/solr package list deployed] +|xref:cli/solr-package-list-installed.adoc[bin/solr package list installed] +|xref:cli/solr-package-undeploy.adoc[bin/solr package undeploy] +|xref:cli/solr-package-uninstall.adoc[bin/solr package uninstall] +|xref:cli/solr-package.adoc[bin/solr package] |xref:cli/solr-start.adoc[bin/solr start] |xref:cli/solr-status.adoc[bin/solr status] |xref:cli/solr-stop.adoc[bin/solr stop] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-add-key.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-add-key.adoc new file mode 100644 index 000000000000..801afac30917 --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-add-key.adoc @@ -0,0 +1,96 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package add key +: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 + +.... +bin/solr package add-key [-hv] [-u=] [-s= | + --solr-url= | -z=] KEY-FILE +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Add a trusted key to Solr. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-h*, *--help*:: + Print this help message and exit. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*-v*, *--verbose*:: + Enable verbose mode. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +_KEY-FILE_:: + Path to a file containing the trusted key. + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # Add a trusted public key + bin/solr package add-key /path/to/public.key.der + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-add-repo.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-add-repo.adoc new file mode 100644 index 000000000000..04f1eccd2fc5 --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-add-repo.adoc @@ -0,0 +1,100 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package add repo +: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 + +.... +bin/solr package add-repo [-hv] [-u=] [-s= | + --solr-url= | -z=] REPOSITORY-NAME + REPOSITORY-URL +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Add a package repository to Solr. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-h*, *--help*:: + Print this help message and exit. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*-v*, *--verbose*:: + Enable verbose mode. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +_REPOSITORY-NAME_:: + Name of the package repository. + +_REPOSITORY-URL_:: + URL of the package repository. + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # Add a package repository + bin/solr package add-repo myrepo https://my.repo.example/repo + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-deploy.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-deploy.adoc new file mode 100644 index 000000000000..9fa3a1217f39 --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-deploy.adoc @@ -0,0 +1,116 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package deploy +: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 + +.... +bin/solr package deploy [-hvy] [--cluster] [--update] [--collections=COLLECTIONS] + [-u=] [-p=PARAMS]... [-s= | + --solr-url= | -z=] PACKAGE[:VERSION] +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Deploy an installed package to collections or at cluster level. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*--cluster*:: + Specifies that this action should affect cluster-level plugins only. + +*--collections*=_COLLECTIONS_:: + Collections on which this package needs to be deployed on, excluding cluster level plugins + +*-h*, *--help*:: + Print this help message and exit. + +*-p*, *--param*=_PARAMS_:: + List of parameters to be used with the deploy command + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*--update*:: + If a deployment is an update over a previous deployment. + +*-v*, *--verbose*:: + Enable verbose mode. + +*-y*, *--no-prompt*:: + Do not prompt for input; accept all default choices, defaults to false. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +_PACKAGE[:VERSION]_:: + Package name, optionally with :version. + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # Deploy a package to a collection + bin/solr package deploy mypkg:1.0.0 --collections myCollection -y + +[%hardbreaks] + # Update an existing deployment + bin/solr package deploy mypkg --update --collections myCollection -y + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-install.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-install.adoc new file mode 100644 index 000000000000..7734cedff149 --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-install.adoc @@ -0,0 +1,100 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package install +: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 + +.... +bin/solr package install [-hv] [-u=] [-s= | + --solr-url= | -z=] PACKAGE[:VERSION] +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Install a package into Solr. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-h*, *--help*:: + Print this help message and exit. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*-v*, *--verbose*:: + Enable verbose mode. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +_PACKAGE[:VERSION]_:: + Package name, optionally with :version. + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # Install a specific package version + bin/solr package install mypkg:1.0.0 + +[%hardbreaks] + # Install the latest available version + bin/solr package install mypkg + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-available.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-available.adoc new file mode 100644 index 000000000000..83110eb433db --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-available.adoc @@ -0,0 +1,88 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package list available +: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 + +.... +bin/solr package list-available [-hv] [-u=] [-s= | + --solr-url= | -z=] +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Print a list of packages available in the repositories. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-h*, *--help*:: + Print this help message and exit. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*-v*, *--verbose*:: + Enable verbose mode. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # List packages available from configured repositories + bin/solr package list-available + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-deployed.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-deployed.adoc new file mode 100644 index 000000000000..c41e70f68ebe --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-deployed.adoc @@ -0,0 +1,104 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package list deployed +: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 + +.... +bin/solr package list-deployed [-hv] [-c=COLLECTION] [-u=] + [-s= | --solr-url= | + -z=] [PACKAGE] +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Print packages deployed on a collection, or collections where a package is deployed. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-c*, *--collection*=_COLLECTION_:: + Collection for which deployed packages are to be listed. + +*-h*, *--help*:: + Print this help message and exit. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*-v*, *--verbose*:: + Enable verbose mode. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +[_PACKAGE_]:: + Package name; lists collections where this package is deployed. + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # List packages deployed on a collection + bin/solr package list-deployed -c myCollection + +[%hardbreaks] + # List collections where a package is deployed + bin/solr package list-deployed mypkg + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-installed.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-installed.adoc new file mode 100644 index 000000000000..216b3e58bfb4 --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-installed.adoc @@ -0,0 +1,88 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package list installed +: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 + +.... +bin/solr package list-installed [-hv] [-u=] [-s= | + --solr-url= | -z=] +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Print a list of packages installed in Solr. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-h*, *--help*:: + Print this help message and exit. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*-v*, *--verbose*:: + Enable verbose mode. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # List all installed packages + bin/solr package list-installed + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-undeploy.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-undeploy.adoc new file mode 100644 index 000000000000..2cc5f1e563f4 --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-undeploy.adoc @@ -0,0 +1,103 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package undeploy +: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 + +.... +bin/solr package undeploy [-hv] [--cluster] [--collections=COLLECTIONS] + [-u=] [-s= | + --solr-url= | -z=] PACKAGE +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Undeploy a package from specified collection(s) or at cluster level. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*--cluster*:: + Specifies that this action should affect cluster-level plugins only. + +*--collections*=_COLLECTIONS_:: + Collections on which this package needs to be undeployed from, excluding cluster level plugins + +*-h*, *--help*:: + Print this help message and exit. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*-v*, *--verbose*:: + Enable verbose mode. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +_PACKAGE_:: + Package name + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # Undeploy a package from a collection + bin/solr package undeploy mypkg --collections myCollection + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-uninstall.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-uninstall.adoc new file mode 100644 index 000000000000..689984fa85ac --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-uninstall.adoc @@ -0,0 +1,96 @@ +// 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. +// +// DO NOT EDIT -- this page is auto-generated from picocli annotations. +// To update: modify the @Command/@Option annotations in the Java source, then run: +// ./gradlew :solr:solr-ref-guide:generateCliDocs + += bin/solr package uninstall +: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 + +.... +bin/solr package uninstall [-hv] [-u=] [-s= | + --solr-url= | -z=] PACKAGE:VERSION +.... + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +Uninstall any package with a specified version from Solr. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-h*, *--help*:: + Print this help message and exit. + +*-s*, *--solr-connection*=__:: + Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +*--solr-url*=__:: + Base Solr URL, which can be used to determine the zk-host if that's not known. + +*-u*, *--credentials*=__:: + Credentials in the format username:password. Example: --credentials solr:SolrRocks + +*-v*, *--verbose*:: + Enable verbose mode. + +*-z*, *--zk-host*=__:: + Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +_PACKAGE:VERSION_:: + Package name and version, separated by a colon. + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-exit-status[] +== Exit Codes +*0*:: + Operation completed successfully. + +*1*:: + Operation failed; check output for details. + +// end::picocli-generated-man-section-exit-status[] + +// tag::picocli-generated-man-section-footer[] +== Examples +[%hardbreaks] + # Uninstall a specific package version + bin/solr package uninstall mypkg:1.0.0 + +// end::picocli-generated-man-section-footer[] diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc index 4fa12edb6ce8..55877c9735c2 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc @@ -22,21 +22,19 @@ = bin/solr package :page-toclevels: 2 -// tag::picocli-generated-man-section-name[] -== Name - -bin/solr package - Install, deploy and manage Solr packages in SolrCloud. - -// end::picocli-generated-man-section-name[] +[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 .... -bin/solr package [-vy] [--cluster] [--update] [-c=COLLECTION] - [--collections=COLLECTIONS] [-u=] [--param=PARAMS]... - [-s= | --solr-url= | -z=] COMMAND - [ARGS...] +bin/solr package [-hv] [-u=] [-s= | + --solr-url= | -z=] [COMMAND] .... // end::picocli-generated-man-section-synopsis[] @@ -44,24 +42,15 @@ bin/solr package [-vy] [--cluster] [--update] [-c=COLLECTION] // tag::picocli-generated-man-section-description[] == Description -Install, deploy and manage Solr packages in SolrCloud. + // end::picocli-generated-man-section-description[] // tag::picocli-generated-man-section-options[] == Options -*-c*, *--collection*=_COLLECTION_:: - The collection to apply the package to. - -*--cluster*:: - Specifies that this action should affect cluster-level plugins only. - -*--collections*=_COLLECTIONS_:: - Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins. - -*--param*=_PARAMS_:: - List of parameters to be used with the deploy command. +*-h*, *--help*:: + Print this help message and exit. *-s*, *--solr-connection*=__:: Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. @@ -72,37 +61,48 @@ Install, deploy and manage Solr packages in SolrCloud. *-u*, *--credentials*=__:: Credentials in the format username:password. Example: --credentials solr:SolrRocks -*--update*:: - If a deployment is an update over a previous deployment. - *-v*, *--verbose*:: Enable verbose mode. -*-y*, *--no-prompt*:: - Don't prompt for input; accept all default choices, defaults to false. - *-z*, *--zk-host*=__:: Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. // end::picocli-generated-man-section-options[] -// tag::picocli-generated-man-section-arguments[] -== Arguments +// tag::picocli-generated-man-section-commands[] +== Commands + +xref:cli/solr-package-add-repo.adoc[*add-repo*]:: + Add a package repository to Solr. -_COMMAND_:: - Package command: add-repo, add-key, list-installed, list-available, list-deployed, install, deploy, undeploy, uninstall. +xref:cli/solr-package-add-key.adoc[*add-key*]:: + Add a trusted key to Solr. -[_ARGS_...]:: - Command-specific arguments (package name[:version], repository name/URL, key file, etc.). +xref:cli/solr-package-list-installed.adoc[*list-installed*]:: + Print a list of packages installed in Solr. -// end::picocli-generated-man-section-arguments[] +xref:cli/solr-package-list-available.adoc[*list-available*]:: + Print a list of packages available in the repositories. + +xref:cli/solr-package-list-deployed.adoc[*list-deployed*]:: + Print packages deployed on a collection, or collections where a package is deployed. + +xref:cli/solr-package-install.adoc[*install*]:: + Install a package into Solr. + +xref:cli/solr-package-deploy.adoc[*deploy*]:: + Deploy an installed package to collections or at cluster level. + +xref:cli/solr-package-undeploy.adoc[*undeploy*]:: + Undeploy a package from specified collection(s) or at cluster level. + +xref:cli/solr-package-uninstall.adoc[*uninstall*]:: + Uninstall any package with a specified version from Solr. -// tag::picocli-generated-man-section-commands[] // end::picocli-generated-man-section-commands[] // tag::picocli-generated-man-section-exit-status[] -== Exit Codes: - +== Exit Codes *0*:: Operation completed successfully. @@ -112,8 +112,7 @@ _COMMAND_:: // end::picocli-generated-man-section-exit-status[] // tag::picocli-generated-man-section-footer[] -== Examples: - +== Examples [%hardbreaks] # Add a package repository bin/solr package add-repo myrepo https://my.repo.example/repo From 91019f1a4567682a22693a900a11d9e7553c68c0 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 14:32:53 +0530 Subject: [PATCH 17/23] tidy ran --- .../src/java/org/apache/solr/cli/AddKey.java | 11 +++--- .../src/java/org/apache/solr/cli/AddRepo.java | 4 ++- .../apache/solr/cli/ConnectionOptions.java | 7 ++-- .../src/java/org/apache/solr/cli/Deploy.java | 28 +++++++++------ .../src/java/org/apache/solr/cli/Install.java | 18 +++++----- .../org/apache/solr/cli/ListAvailable.java | 11 +++--- .../org/apache/solr/cli/ListDeployed.java | 18 +++++----- .../org/apache/solr/cli/ListInstalled.java | 11 +++--- .../apache/solr/cli/PackageSubCommand.java | 7 ++-- .../java/org/apache/solr/cli/PackageTool.java | 36 +++++++++---------- .../java/org/apache/solr/cli/Undeploy.java | 14 ++++---- .../java/org/apache/solr/cli/Uninstall.java | 15 ++++---- 12 files changed, 95 insertions(+), 85 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/AddKey.java b/solr/core/src/java/org/apache/solr/cli/AddKey.java index 167c4295a5c8..0f0c9347380c 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddKey.java +++ b/solr/core/src/java/org/apache/solr/cli/AddKey.java @@ -26,13 +26,13 @@ description = "Add a trusted key to Solr.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0: Operation completed successfully.", - "1: Operation failed; check output for details." + "0: Operation completed successfully.", + "1: Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # Add a trusted public key", - " bin/solr package add-key /path/to/public.key.der", + " # Add a trusted public key", + " bin/solr package add-key /path/to/public.key.der", }) public class AddKey extends PackageSubCommand { @@ -45,7 +45,8 @@ public class AddKey extends PackageSubCommand { @Override public int callTool() throws Exception { - return runWithManagers(((packageManager, repositoryManager) -> packageTool.addKey(repositoryManager, keyFile))); + return runWithManagers( + ((packageManager, repositoryManager) -> packageTool.addKey(repositoryManager, keyFile))); } @Override diff --git a/solr/core/src/java/org/apache/solr/cli/AddRepo.java b/solr/core/src/java/org/apache/solr/cli/AddRepo.java index 56fd05a31d34..e9c24d724293 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddRepo.java +++ b/solr/core/src/java/org/apache/solr/cli/AddRepo.java @@ -50,7 +50,9 @@ public class AddRepo extends PackageSubCommand { @Override public int callTool() throws Exception { - return runWithManagers(((packageManager, repositoryManager) -> packageTool.addRepo(repositoryManager, repoName, repoUrl))); + return runWithManagers( + ((packageManager, repositoryManager) -> + packageTool.addRepo(repositoryManager, repoName, repoUrl))); } @Override diff --git a/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java b/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java index db7305647aa2..b17518a3e647 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java +++ b/solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java @@ -77,7 +77,8 @@ String effectiveSolrUrl() throws IOException { return solrUrl; } - static String resolveSolrUrl(ConnectionOptions connectionOptions, String credentials) throws Exception { + static String resolveSolrUrl(ConnectionOptions connectionOptions, String credentials) + throws Exception { if (connectionOptions != null) { String solrUrl = connectionOptions.effectiveSolrUrl(); if (solrUrl != null) { @@ -113,8 +114,8 @@ static String resolveSolrUrl(ConnectionOptions connectionOptions, String credent return defaultUrl; } - static String resolveZkHost(ConnectionOptions connectionOptions, String solrUrl, String credentials) - throws Exception { + static String resolveZkHost( + ConnectionOptions connectionOptions, String solrUrl, String credentials) throws Exception { if (connectionOptions != null) { String zkHost = connectionOptions.effectiveZkHost(); if (zkHost != null) { diff --git a/solr/core/src/java/org/apache/solr/cli/Deploy.java b/solr/core/src/java/org/apache/solr/cli/Deploy.java index b3ff8f47acb5..7bc4dc96ae66 100644 --- a/solr/core/src/java/org/apache/solr/cli/Deploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Deploy.java @@ -17,8 +17,6 @@ package org.apache.solr.cli; -import java.nio.file.Path; - import static org.apache.solr.cli.SolrCLI.printRed; /** Supports package add-repo command in the bin/solr script. */ @@ -28,16 +26,16 @@ description = "Deploy an installed package to collections or at cluster level.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0: Operation completed successfully.", - "1: Operation failed; check output for details." + "0: Operation completed successfully.", + "1: Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # Deploy a package to a collection", - " bin/solr package deploy mypkg:1.0.0 --collections myCollection -y", - "", - " # Update an existing deployment", - " bin/solr package deploy mypkg --update --collections myCollection -y" + " # Deploy a package to a collection", + " bin/solr package deploy mypkg:1.0.0 --collections myCollection -y", + "", + " # Update an existing deployment", + " bin/solr package deploy mypkg --update --collections myCollection -y" }) public class Deploy extends PackageSubCommand { @@ -56,7 +54,8 @@ public class Deploy extends PackageSubCommand { @picocli.CommandLine.Option( names = {"--collections"}, paramLabel = "COLLECTIONS", - description = "Collections on which this package needs to be deployed on, excluding cluster level plugins") + description = + "Collections on which this package needs to be deployed on, excluding cluster level plugins") private String collections; @picocli.CommandLine.Option( @@ -84,7 +83,14 @@ public int callTool() throws Exception { } return runWithManagers( (packageManager, repositoryManager) -> - packageTool.deploy(packageManager, packageNameAndVersion, cluster, collections, params, update, noPrompt)); + packageTool.deploy( + packageManager, + packageNameAndVersion, + cluster, + collections, + params, + update, + noPrompt)); } @Override diff --git a/solr/core/src/java/org/apache/solr/cli/Install.java b/solr/core/src/java/org/apache/solr/cli/Install.java index 289a6678c940..66aa68c75f42 100644 --- a/solr/core/src/java/org/apache/solr/cli/Install.java +++ b/solr/core/src/java/org/apache/solr/cli/Install.java @@ -24,16 +24,16 @@ description = "Install a package into Solr.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0: Operation completed successfully.", - "1: Operation failed; check output for details." + "0: Operation completed successfully.", + "1: Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # Install a specific package version", - " bin/solr package install mypkg:1.0.0", - "", - " # Install the latest available version", - " bin/solr package install mypkg" + " # Install a specific package version", + " bin/solr package install mypkg:1.0.0", + "", + " # Install the latest available version", + " bin/solr package install mypkg" }) public class Install extends PackageSubCommand { @@ -47,7 +47,9 @@ public class Install extends PackageSubCommand { @Override public int callTool() throws Exception { final boolean[] status = {true}; - runWithManagers((packageManager, repositoryManager) -> status[0] = packageTool.install(repositoryManager, packageNameAndVersion)); + runWithManagers( + (packageManager, repositoryManager) -> + status[0] = packageTool.install(repositoryManager, packageNameAndVersion)); return status[0] ? 0 : 1; } diff --git a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java index 02915e696b50..3ae58e9d9f83 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java +++ b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java @@ -24,19 +24,20 @@ description = "Print a list of packages available in the repositories.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0: Operation completed successfully.", - "1: Operation failed; check output for details." + "0: Operation completed successfully.", + "1: Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # List packages available from configured repositories", - " bin/solr package list-available", + " # List packages available from configured repositories", + " bin/solr package list-available", }) public class ListAvailable extends PackageSubCommand { @Override public int callTool() throws Exception { - return runWithManagers((packageManager, repositoryManager) -> packageTool.listAvailable(repositoryManager)); + return runWithManagers( + (packageManager, repositoryManager) -> packageTool.listAvailable(repositoryManager)); } @Override diff --git a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java index e269396b4255..b4fffc15f9f6 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java +++ b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java @@ -23,19 +23,20 @@ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "list-deployed", - description = "Print packages deployed on a collection, or collections where a package is deployed.", + description = + "Print packages deployed on a collection, or collections where a package is deployed.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0: Operation completed successfully.", - "1: Operation failed; check output for details." + "0: Operation completed successfully.", + "1: Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # List packages deployed on a collection", - " bin/solr package list-deployed -c myCollection", - "", - " # List collections where a package is deployed", - " bin/solr package list-deployed mypkg" + " # List packages deployed on a collection", + " bin/solr package list-deployed -c myCollection", + "", + " # List collections where a package is deployed", + " bin/solr package list-deployed mypkg" }) public class ListDeployed extends PackageSubCommand { @@ -52,7 +53,6 @@ public class ListDeployed extends PackageSubCommand { description = "Package name; lists collections where this package is deployed.") private String packageName; - @Override public int callTool() throws Exception { if (collection == null && packageName == null) { diff --git a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java index a85666cad62b..fbca565b7443 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java +++ b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java @@ -24,19 +24,20 @@ description = "Print a list of packages installed in Solr.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0: Operation completed successfully.", - "1: Operation failed; check output for details." + "0: Operation completed successfully.", + "1: Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # List all installed packages", - " bin/solr package list-installed", + " # List all installed packages", + " bin/solr package list-installed", }) public class ListInstalled extends PackageSubCommand { @Override public int callTool() throws Exception { - return runWithManagers((packageManager, repositoryManager) -> packageTool.listInstalled(packageManager)); + return runWithManagers( + (packageManager, repositoryManager) -> packageTool.listInstalled(packageManager)); } @Override diff --git a/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java index 169f3011f514..2a1ae5de3746 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java @@ -34,7 +34,6 @@ interface PackageAction { @picocli.CommandLine.Mixin CredentialsOptions credentialsOptions; @picocli.CommandLine.ArgGroup(exclusive = true, multiplicity = "0..1") - ConnectionOptions connectionOptions; PackageSubCommand() { @@ -44,8 +43,7 @@ interface PackageAction { @Override public void runImpl(CommandLine cli) throws Exception { throw new UnsupportedOperationException( - getName() + " is implemented via the commons-cli path under PackageTool" - ); + getName() + " is implemented via the commons-cli path under PackageTool"); } final int runWithManagers(PackageAction action) throws Exception { @@ -59,8 +57,7 @@ final int runWithManagers(PackageAction action) throws Exception { packageTool.runWithManagers( connectionOptions != null ? connectionOptions : packageTool.connectionOptions, credentials, - action - ); + action); return 0; } } 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 d63fa8af113c..3be99424ea87 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -58,15 +58,15 @@ }, footerHeading = "%nExamples:%n", subcommands = { - AddRepo.class, - AddKey.class, - ListInstalled.class, - ListAvailable.class, - ListDeployed.class, - Install.class, - Deploy.class, - Undeploy.class, - Uninstall.class + AddRepo.class, + AddKey.class, + ListInstalled.class, + ListAvailable.class, + ListDeployed.class, + Install.class, + Deploy.class, + Undeploy.class, + Uninstall.class }, footer = { " # Add a package repository", @@ -158,7 +158,6 @@ public String getName() { return "package"; } - @Override public void runImpl(CommandLine cli) throws Exception { String credentials = cli.getOptionValue(CommonCLIOptions.CREDENTIALS_OPTION); @@ -222,12 +221,10 @@ private void executePackage( } /** - * Picocli subcommand path: resolve connection, open managers, run action, close. - * Commons-cli runs through {@link #executePackage(CommandLine, String, String, String[], PackageFlags)} instead. + * Picocli subcommand path: resolve connection, open managers, run action, close. Commons-cli runs + * through {@link #executePackage(CommandLine, String, String, String[], PackageFlags)} instead. */ - @SuppressForbidden( - reason = - "TBA") + @SuppressForbidden(reason = "TBA") void runWithManagers( ConnectionOptions opts, String credentials, PackageSubCommand.PackageAction action) throws Exception { @@ -263,7 +260,8 @@ void runWithManagers( } } - void addRepo(RepositoryManager repositoryManager, String repoName, String repoUrl) throws Exception { + void addRepo(RepositoryManager repositoryManager, String repoName, String repoUrl) + throws Exception { repositoryManager.addRepository(repoName, repoUrl); printGreen("Added repository: " + repoName); } @@ -376,8 +374,7 @@ void undeploy( packageManager.undeploy(packageName, collectionArray, cluster); } - void uninstall(PackageManager packageManager, String packageNameAndVersion) - throws Exception { + void uninstall(PackageManager packageManager, String packageNameAndVersion) throws Exception { Pair parsedVersion = parsePackageVersion(packageNameAndVersion); if (parsedVersion.second() == null) { throw new SolrException( @@ -429,8 +426,7 @@ private void handleCommand(String command, String[] cmdArgs, PackageFlags packag break; case "undeploy": if (packageFlags.cluster() || packageFlags.collections() != null) { - undeploy( - packageManager, cmdArgs[0], packageFlags.cluster(), packageFlags.collections()); + undeploy(packageManager, cmdArgs[0], packageFlags.cluster(), packageFlags.collections()); } else { printRed( "Either specify --cluster to undeploy cluster level plugins or -collections to undeploy collection level plugins"); diff --git a/solr/core/src/java/org/apache/solr/cli/Undeploy.java b/solr/core/src/java/org/apache/solr/cli/Undeploy.java index 462a11a6f2b6..852498f9cc52 100644 --- a/solr/core/src/java/org/apache/solr/cli/Undeploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Undeploy.java @@ -26,13 +26,13 @@ description = "Undeploy a package from specified collection(s) or at cluster level.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0: Operation completed successfully.", - "1: Operation failed; check output for details." + "0: Operation completed successfully.", + "1: Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # Undeploy a package from a collection", - " bin/solr package undeploy mypkg --collections myCollection" + " # Undeploy a package from a collection", + " bin/solr package undeploy mypkg --collections myCollection" }) public class Undeploy extends PackageSubCommand { @@ -51,7 +51,8 @@ public class Undeploy extends PackageSubCommand { @picocli.CommandLine.Option( names = {"--collections"}, paramLabel = "COLLECTIONS", - description = "Collections on which this package needs to be undeployed from, excluding cluster level plugins") + description = + "Collections on which this package needs to be undeployed from, excluding cluster level plugins") private String collections; @Override @@ -62,7 +63,8 @@ public int callTool() throws Exception { return 1; } return runWithManagers( - (packageManager, repositoryManager) -> packageTool.undeploy(packageManager, packageName, cluster, collections)); + (packageManager, repositoryManager) -> + packageTool.undeploy(packageManager, packageName, cluster, collections)); } @Override diff --git a/solr/core/src/java/org/apache/solr/cli/Uninstall.java b/solr/core/src/java/org/apache/solr/cli/Uninstall.java index bdbd5517b242..81ff5921b011 100644 --- a/solr/core/src/java/org/apache/solr/cli/Uninstall.java +++ b/solr/core/src/java/org/apache/solr/cli/Uninstall.java @@ -21,17 +21,16 @@ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "uninstall", - description = - "Uninstall any package with a specified version from Solr.", + description = "Uninstall any package with a specified version from Solr.", exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { - "0: Operation completed successfully.", - "1: Operation failed; check output for details." + "0: Operation completed successfully.", + "1: Operation failed; check output for details." }, footerHeading = "%nExamples:%n", footer = { - " # Uninstall a specific package version", - " bin/solr package uninstall mypkg:1.0.0", + " # Uninstall a specific package version", + " bin/solr package uninstall mypkg:1.0.0", }) public class Uninstall extends PackageSubCommand { @@ -44,7 +43,9 @@ public class Uninstall extends PackageSubCommand { @Override public int callTool() throws Exception { - return runWithManagers((packageManager, repositoryManager) -> packageTool.uninstall(packageManager, packageNameAndVersion)); + return runWithManagers( + (packageManager, repositoryManager) -> + packageTool.uninstall(packageManager, packageNameAndVersion)); } @Override From 41478762021b370b46a2c8f37eea880e553880f1 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 14:40:10 +0530 Subject: [PATCH 18/23] minor --- solr/core/src/java/org/apache/solr/cli/AddKey.java | 2 +- solr/core/src/java/org/apache/solr/cli/Deploy.java | 2 +- solr/core/src/java/org/apache/solr/cli/Install.java | 2 +- solr/core/src/java/org/apache/solr/cli/ListAvailable.java | 2 +- solr/core/src/java/org/apache/solr/cli/ListDeployed.java | 2 +- solr/core/src/java/org/apache/solr/cli/ListInstalled.java | 2 +- solr/core/src/java/org/apache/solr/cli/Undeploy.java | 2 +- solr/core/src/java/org/apache/solr/cli/Uninstall.java | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/AddKey.java b/solr/core/src/java/org/apache/solr/cli/AddKey.java index 0f0c9347380c..9cdd6414b10d 100644 --- a/solr/core/src/java/org/apache/solr/cli/AddKey.java +++ b/solr/core/src/java/org/apache/solr/cli/AddKey.java @@ -19,7 +19,7 @@ import java.nio.file.Path; -/** Supports package add-repo command in the bin/solr script. */ +/** Supports package add-key command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "add-key", diff --git a/solr/core/src/java/org/apache/solr/cli/Deploy.java b/solr/core/src/java/org/apache/solr/cli/Deploy.java index 7bc4dc96ae66..e84741941c1b 100644 --- a/solr/core/src/java/org/apache/solr/cli/Deploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Deploy.java @@ -19,7 +19,7 @@ import static org.apache.solr.cli.SolrCLI.printRed; -/** Supports package add-repo command in the bin/solr script. */ +/** Supports package deploy command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "deploy", diff --git a/solr/core/src/java/org/apache/solr/cli/Install.java b/solr/core/src/java/org/apache/solr/cli/Install.java index 66aa68c75f42..1e38f7d67cd4 100644 --- a/solr/core/src/java/org/apache/solr/cli/Install.java +++ b/solr/core/src/java/org/apache/solr/cli/Install.java @@ -17,7 +17,7 @@ package org.apache.solr.cli; -/** Supports package add-repo command in the bin/solr script. */ +/** Supports package install command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "install", diff --git a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java index 3ae58e9d9f83..c5f2fe7a124b 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListAvailable.java +++ b/solr/core/src/java/org/apache/solr/cli/ListAvailable.java @@ -17,7 +17,7 @@ package org.apache.solr.cli; -/** Supports package add-repo command in the bin/solr script. */ +/** Supports package list-available command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "list-available", diff --git a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java index b4fffc15f9f6..c2f78336dd27 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java +++ b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java @@ -19,7 +19,7 @@ import static org.apache.solr.cli.SolrCLI.printRed; -/** Supports package add-repo command in the bin/solr script. */ +/** Supports package list-deployed command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "list-deployed", diff --git a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java index fbca565b7443..ec936a0331d3 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListInstalled.java +++ b/solr/core/src/java/org/apache/solr/cli/ListInstalled.java @@ -17,7 +17,7 @@ package org.apache.solr.cli; -/** Supports package add-repo command in the bin/solr script. */ +/** Supports package list-installed command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "list-installed", diff --git a/solr/core/src/java/org/apache/solr/cli/Undeploy.java b/solr/core/src/java/org/apache/solr/cli/Undeploy.java index 852498f9cc52..c24083ae1a66 100644 --- a/solr/core/src/java/org/apache/solr/cli/Undeploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Undeploy.java @@ -19,7 +19,7 @@ import static org.apache.solr.cli.SolrCLI.printRed; -/** Supports package add-repo command in the bin/solr script. */ +/** Supports package undeploy command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "undeploy", diff --git a/solr/core/src/java/org/apache/solr/cli/Uninstall.java b/solr/core/src/java/org/apache/solr/cli/Uninstall.java index 81ff5921b011..0a45b0ba76cd 100644 --- a/solr/core/src/java/org/apache/solr/cli/Uninstall.java +++ b/solr/core/src/java/org/apache/solr/cli/Uninstall.java @@ -17,7 +17,7 @@ package org.apache.solr.cli; -/** Supports package add-repo command in the bin/solr script. */ +/** Supports package uninstall command in the bin/solr script. */ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "uninstall", From e7c3693ce38c2cb92ff62e13498449ff1e6b3f42 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 14:54:23 +0530 Subject: [PATCH 19/23] pr comments --- solr/core/src/java/org/apache/solr/cli/PackageTool.java | 7 ++++++- .../modules/deployment-guide/pages/cli/solr-package.adoc | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) 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 3be99424ea87..227dbfa9363c 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -50,7 +50,12 @@ @SuppressWarnings("UnnecessarilyFullyQualified") @picocli.CommandLine.Command( name = "package", - description = "", + description = { + "Install, deploy and manage Solr packages in SolrCloud.", + "Pass --help or -h after any command to see command-specific usage information.", + " Note: (a) Please add '--solr-url http://host:port' parameter if needed (usually on Windows).", + " (b) Please make sure that all solr nodes are started with '-Dsolr.packages.enabled=true'." + }, exitCodeListHeading = "%nExit Codes:%n", exitCodeList = { "0:Operation completed successfully.", diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc index 55877c9735c2..ba00cf3e03b3 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc @@ -42,7 +42,10 @@ bin/solr package [-hv] [-u=] [-s= | // tag::picocli-generated-man-section-description[] == Description - +Install, deploy and manage Solr packages in SolrCloud. +Pass --help or -h after any command to see command-specific usage information. + Note: (a) Please add '--solr-url http://host:port' parameter if needed (usually on Windows). + (b) Please make sure that all solr nodes are started with '-Dsolr.packages.enabled=true'. // end::picocli-generated-man-section-description[] From 670cb97af69815effc2889986e68b2d508a8966e Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 15:03:21 +0530 Subject: [PATCH 20/23] minor --- .../src/java/org/apache/solr/cli/PackageTool.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) 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 227dbfa9363c..b1f85c4b2fc3 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -32,11 +32,11 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configurator; +import org.apache.lucene.util.SuppressForbidden; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.util.Pair; -import org.apache.solr.common.util.SuppressForbidden; import org.apache.solr.packagemanager.PackageManager; import org.apache.solr.packagemanager.PackageUtils; import org.apache.solr.packagemanager.RepositoryManager; @@ -180,7 +180,12 @@ public void runImpl(CommandLine cli) throws Exception { executePackage(cli, credentials, command, cmdArgs, packageFlags); } - @SuppressForbidden(reason = "TBA") + @SuppressForbidden( + reason = + "We really need to print the stacktrace here, otherwise " + + "there shall be little else information to debug problems. Other SolrCLI tools " + + "don't print stack traces, hence special treatment is needed here." + + "Need to turn off logging, and SLF4J doesn't seem to provide for a way.") private void executePackage( CommandLine cli, String credentials, @@ -229,7 +234,9 @@ private void executePackage( * Picocli subcommand path: resolve connection, open managers, run action, close. Commons-cli runs * through {@link #executePackage(CommandLine, String, String, String[], PackageFlags)} instead. */ - @SuppressForbidden(reason = "TBA") + @SuppressForbidden( + reason = + "Package tool prints stack traces and turns off logging; this is same as executePackage.") void runWithManagers( ConnectionOptions opts, String credentials, PackageSubCommand.PackageAction action) throws Exception { From 2142ded3501d7c92e0bcbdc40da32fc437731b55 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 15:37:40 +0530 Subject: [PATCH 21/23] pr comments --- solr/core/src/java/org/apache/solr/cli/Deploy.java | 6 +++--- solr/core/src/java/org/apache/solr/cli/ListDeployed.java | 2 +- solr/core/src/java/org/apache/solr/cli/Undeploy.java | 2 +- .../deployment-guide/pages/cli/solr-package-deploy.adoc | 6 +++--- .../pages/cli/solr-package-list-deployed.adoc | 2 +- .../deployment-guide/pages/cli/solr-package-undeploy.adoc | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/Deploy.java b/solr/core/src/java/org/apache/solr/cli/Deploy.java index e84741941c1b..4e27c9809e8c 100644 --- a/solr/core/src/java/org/apache/solr/cli/Deploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Deploy.java @@ -55,13 +55,13 @@ public class Deploy extends PackageSubCommand { names = {"--collections"}, paramLabel = "COLLECTIONS", description = - "Collections on which this package needs to be deployed on, excluding cluster level plugins") + "Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins.") private String collections; @picocli.CommandLine.Option( names = {"-p", "--param"}, paramLabel = "PARAMS", - description = "List of parameters to be used with the deploy command") + description = "List of parameters to be used with deploy command.") private String[] params; @picocli.CommandLine.Option( @@ -71,7 +71,7 @@ public class Deploy extends PackageSubCommand { @picocli.CommandLine.Option( names = {"-y", "--no-prompt"}, - description = "Do not prompt for input; accept all default choices, defaults to false.") + description = "Don't prompt for input; accept all default choices, defaults to false.") private boolean noPrompt; @Override diff --git a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java index c2f78336dd27..1303502e70c0 100644 --- a/solr/core/src/java/org/apache/solr/cli/ListDeployed.java +++ b/solr/core/src/java/org/apache/solr/cli/ListDeployed.java @@ -43,7 +43,7 @@ public class ListDeployed extends PackageSubCommand { @picocli.CommandLine.Option( names = {"-c", "--collection"}, paramLabel = "COLLECTION", - description = "Collection for which deployed packages are to be listed.") + description = "The collection to apply the package to, not required.") private String collection; @picocli.CommandLine.Parameters( diff --git a/solr/core/src/java/org/apache/solr/cli/Undeploy.java b/solr/core/src/java/org/apache/solr/cli/Undeploy.java index c24083ae1a66..7c1939aa6f7e 100644 --- a/solr/core/src/java/org/apache/solr/cli/Undeploy.java +++ b/solr/core/src/java/org/apache/solr/cli/Undeploy.java @@ -52,7 +52,7 @@ public class Undeploy extends PackageSubCommand { names = {"--collections"}, paramLabel = "COLLECTIONS", description = - "Collections on which this package needs to be undeployed from, excluding cluster level plugins") + "Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins.") private String collections; @Override diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-deploy.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-deploy.adoc index 9fa3a1217f39..cd1b181a2a41 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-deploy.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-deploy.adoc @@ -54,13 +54,13 @@ Deploy an installed package to collections or at cluster level. Specifies that this action should affect cluster-level plugins only. *--collections*=_COLLECTIONS_:: - Collections on which this package needs to be deployed on, excluding cluster level plugins + Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins. *-h*, *--help*:: Print this help message and exit. *-p*, *--param*=_PARAMS_:: - List of parameters to be used with the deploy command + List of parameters to be used with deploy command. *-s*, *--solr-connection*=__:: Zookeeper or HTTP(s) connection string; unnecessary if SOLR_CONNECTION is defined in solr.in.sh; otherwise, defaults to localhost:9983. @@ -78,7 +78,7 @@ Deploy an installed package to collections or at cluster level. Enable verbose mode. *-y*, *--no-prompt*:: - Do not prompt for input; accept all default choices, defaults to false. + Don't prompt for input; accept all default choices, defaults to false. *-z*, *--zk-host*=__:: Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to localhost:9983. diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-deployed.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-deployed.adoc index c41e70f68ebe..ecd8cdfb609d 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-deployed.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-list-deployed.adoc @@ -51,7 +51,7 @@ Print packages deployed on a collection, or collections where a package is deplo == Options *-c*, *--collection*=_COLLECTION_:: - Collection for which deployed packages are to be listed. + The collection to apply the package to, not required. *-h*, *--help*:: Print this help message and exit. diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-undeploy.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-undeploy.adoc index 2cc5f1e563f4..dd61fbb36a0d 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-undeploy.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package-undeploy.adoc @@ -54,7 +54,7 @@ Undeploy a package from specified collection(s) or at cluster level. Specifies that this action should affect cluster-level plugins only. *--collections*=_COLLECTIONS_:: - Collections on which this package needs to be undeployed from, excluding cluster level plugins + Specifies that this action should affect plugins for the given collections only, excluding cluster level plugins. *-h*, *--help*:: Print this help message and exit. From eb59da52fa35722b5d5998f5ff1040d312d15782 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 15:55:59 +0530 Subject: [PATCH 22/23] added CL --- changelog/unreleased/SOLR-17697-packagetool.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 changelog/unreleased/SOLR-17697-packagetool.yml diff --git a/changelog/unreleased/SOLR-17697-packagetool.yml b/changelog/unreleased/SOLR-17697-packagetool.yml new file mode 100644 index 000000000000..ac5d963a050e --- /dev/null +++ b/changelog/unreleased/SOLR-17697-packagetool.yml @@ -0,0 +1,9 @@ +title: + Implement picocli for package command / PackageTool +type: changed +authors: + - name: Jalaz Kumar + nick: jaykay12 +links: + - name: SOLR-17697 + url: https://issues.apache.org/jira/browse/SOLR-17697 From 970ee26294254f854e3b269d3f0a5c024af5087a Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 16:05:53 +0530 Subject: [PATCH 23/23] minor --- solr/core/src/java/org/apache/solr/cli/PackageTool.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b1f85c4b2fc3..2040cc591392 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -441,7 +441,7 @@ private void handleCommand(String command, String[] cmdArgs, PackageFlags packag undeploy(packageManager, cmdArgs[0], packageFlags.cluster(), packageFlags.collections()); } else { printRed( - "Either specify --cluster to undeploy cluster level plugins or -collections to undeploy collection level plugins"); + "Either specify --cluster to undeploy cluster level plugins or --collections to undeploy collection level plugins"); } break; case "uninstall":