diff --git a/changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml b/changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml index 0603e293c110..2c102eb62aca 100644 --- a/changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml +++ b/changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml @@ -8,6 +8,8 @@ authors: - name: Jan Høydahl url: https://home.apache.org/phonebook.html?uid=janhoy - name: Serhiy Bzhezytskyy + - name: Jalaz Kumar + nick: jaykay12 links: - name: SOLR-17697 url: https://issues.apache.org/jira/browse/SOLR-17697 @@ -31,3 +33,5 @@ links: url: https://issues.apache.org/jira/browse/SOLR-18518 - name: SOLR-18517 url: https://issues.apache.org/jira/browse/SOLR-18517 + - name: SOLR-18515 + url: https://issues.apache.org/jira/browse/SOLR-18515 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..57ee0532faaa 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,82 @@ String effectiveSolrUrl() throws IOException { } return solrUrl; } + + static String resolveSolrUrl(ConnectionOptions connectionOptions, 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 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 " + + defaultUrl + + "."); + return defaultUrl; + } + + static String resolveZkHost( + ConnectionOptions connectionOptions, String solrUrl, String credentials) throws Exception { + boolean resolveFromSolrUrl = false; + if (connectionOptions != null) { + String zkHost = connectionOptions.effectiveZkHost(); + if (zkHost != null) { + return zkHost; + } + resolveFromSolrUrl = connectionOptions.effectiveSolrUrl() != null; + } + + if (!resolveFromSolrUrl) { + 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") + 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/PackageAddKey.java b/solr/core/src/java/org/apache/solr/cli/PackageAddKey.java new file mode 100644 index 000000000000..97f6bc286beb --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageAddKey.java @@ -0,0 +1,56 @@ +/* + * 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 java.nio.file.Path; + +/** Supports package add-key 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 PackageAddKey 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/PackageAddRepo.java b/solr/core/src/java/org/apache/solr/cli/PackageAddRepo.java new file mode 100644 index 000000000000..cb3bc7067a32 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageAddRepo.java @@ -0,0 +1,62 @@ +/* + * 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; + +/** 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 PackageAddRepo extends PackageSubCommand { + + @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.") + private String repoUrl; + + @Override + public int callTool() throws Exception { + return runWithManagers( + ((packageManager, repositoryManager) -> + packageTool.addRepo(repositoryManager, repoName, repoUrl))); + } + + @Override + public String getName() { + return "add-repo"; + } +} diff --git a/solr/core/src/java/org/apache/solr/cli/PackageDeploy.java b/solr/core/src/java/org/apache/solr/cli/PackageDeploy.java new file mode 100644 index 000000000000..ff24a7a1692d --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageDeploy.java @@ -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. + */ + +package org.apache.solr.cli; + +import static org.apache.solr.cli.SolrCLI.printRed; + +/** Supports package deploy 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 PackageDeploy 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 = + "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 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 = "Don't 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/PackageInstall.java b/solr/core/src/java/org/apache/solr/cli/PackageInstall.java new file mode 100644 index 000000000000..b48c65f4a120 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageInstall.java @@ -0,0 +1,60 @@ +/* + * 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; + +/** Supports package install 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 PackageInstall 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/PackageListAvailable.java b/solr/core/src/java/org/apache/solr/cli/PackageListAvailable.java new file mode 100644 index 000000000000..e0420ecb7d46 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageListAvailable.java @@ -0,0 +1,47 @@ +/* + * 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; + +/** Supports package list-available 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 PackageListAvailable 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/PackageListDeployed.java b/solr/core/src/java/org/apache/solr/cli/PackageListDeployed.java new file mode 100644 index 000000000000..944fce6591b0 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageListDeployed.java @@ -0,0 +1,77 @@ +/* + * 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.printRed; + +/** Supports package list-deployed 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 PackageListDeployed extends PackageSubCommand { + + @picocli.CommandLine.Option( + names = {"-c", "--collection"}, + paramLabel = "COLLECTION", + description = "The collection to apply the package to, not required.") + 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/PackageListInstalled.java b/solr/core/src/java/org/apache/solr/cli/PackageListInstalled.java new file mode 100644 index 000000000000..e1d62b26d956 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageListInstalled.java @@ -0,0 +1,47 @@ +/* + * 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; + +/** Supports package list-installed 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 PackageListInstalled 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/PackageSubCommand.java b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java new file mode 100644 index 000000000000..9b8130227af1 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java @@ -0,0 +1,64 @@ +/* + * 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} */ +@SuppressWarnings("UnnecessarilyFullyQualified") +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.credentialsOptions != null + ? packageTool.credentialsOptions.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 cba26c58a3a9..5e7ebe39a9d6 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; @@ -46,6 +47,43 @@ 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.", + "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.", + "1:Operation failed; check output for details." + }, + footerHeading = "%nExamples:%n", + subcommands = { + PackageAddRepo.class, + PackageAddKey.class, + PackageListInstalled.class, + PackageListAvailable.class, + PackageListDeployed.class, + PackageInstall.class, + PackageDeploy.class, + PackageUndeploy.class, + PackageUninstall.class + }, + footer = { + " # Add a package repository", + " 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", + " 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 +131,29 @@ 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, + String[] parameters, + boolean update, + String collection, + boolean noPrompt) {} + + @picocli.CommandLine.ArgGroup(exclusive = true, multiplicity = "0..1") + ConnectionOptions connectionOptions; + + @picocli.CommandLine.Mixin CredentialsOptions credentialsOptions; + + @picocli.CommandLine.Spec private picocli.CommandLine.Model.CommandSpec spec; + + private PackageManager packageManager; + private RepositoryManager repositoryManager; + + public PackageTool() { + this(new DefaultToolRuntime()); + } + public PackageTool(ToolRuntime runtime) { super(runtime); } @@ -102,17 +163,36 @@ public String getName() { return "package"; } - public PackageManager packageManager; - public RepositoryManager repositoryManager; - @Override + 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)); + + executePackage(cli, credentials, command, cmdArgs, packageFlags); + } + @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 { + private void executePackage( + CommandLine cli, + 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(); @@ -121,83 +201,23 @@ public void runImpl(CommandLine cli) throws Exception { 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( - solrUrl, cli.getOptionValue(CommonCLIOptions.CREDENTIALS_OPTION), true)) { + try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, credentials, true)) { packageManager = new PackageManager(runtime, solrClient, solrUrl, zkHost); try { repositoryManager = new RepositoryManager(solrClient, packageManager); - - // Dispatches to a parser-independent method per sub-command - switch (cmd) { - case "add-repo": - addRepo(cli.getArgs()[1], cli.getArgs()[2]); - break; - case "add-key": - addKey(Path.of(cli.getArgs()[1])); - break; - case "list-installed": - listInstalled(); - break; - case "list-available": - listAvailable(); - break; - case "list-deployed": - if (cli.hasOption(COLLECTION_OPTION)) { - listPackagesDeployedOnCollection(cli.getOptionValue(COLLECTION_OPTION)); - } 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]); - } - break; - case "install": - install(cli.getArgList().get(1)); - break; - case "deploy": - if (cli.hasOption(CLUSTER_OPTION) || cli.hasOption(COLLECTIONS_OPTION)) { - 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)); - } 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)) { - undeploy( - cli.getArgList().get(1), - cli.hasOption(CLUSTER_OPTION), - cli.getOptionValue(COLLECTIONS_OPTION)); - } 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)); - break; - default: - throw new RuntimeException("Unrecognized command: " + cmd); - } + handleCommand(command, cmdArgs, packageFlags); } finally { 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 @@ -210,23 +230,66 @@ public void runImpl(CommandLine cli) throws Exception { } } - 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 = + "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 { + // 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); @@ -236,7 +299,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()) { @@ -244,7 +307,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:"); @@ -263,7 +326,8 @@ private void listCollectionsWithPackageDeployed(String packageName) { } } - private void install(String packageNameAndVersion) throws Exception { + boolean install(RepositoryManager repositoryManager, String packageNameAndVersion) + throws Exception { Pair parsedVersion = parsePackageVersion(packageNameAndVersion); String packageName = parsedVersion.first(); String version = parsedVersion.second(); @@ -273,12 +337,14 @@ private void install(String packageNameAndVersion) throws Exception { } else { printRed(packageName + " installation failed."); } + return success; } /** * @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, @@ -300,7 +366,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) { @@ -316,7 +386,7 @@ 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( @@ -326,6 +396,62 @@ private void uninstall(String packageNameAndVersion) throws Exception { packageManager.uninstall(parsedVersion.first(), parsedVersion.second()); } + private void handleCommand(String command, String[] cmdArgs, PackageFlags packageFlags) + throws Exception { + switch (command) { + case "add-repo": + addRepo(repositoryManager, cmdArgs[0], cmdArgs[1]); + break; + case "add-key": + addKey(repositoryManager, Path.of(cmdArgs[0])); + break; + case "list-installed": + listInstalled(packageManager); + break; + case "list-available": + listAvailable(repositoryManager); + break; + case "list-deployed": + if (packageFlags.collection() != null) { + listPackagesDeployedOnCollection(packageManager, packageFlags.collection()); + } else { + listCollectionsWithPackageDeployed(packageManager, cmdArgs[0]); + } + break; + case "install": + install(repositoryManager, cmdArgs[0]); + break; + case "deploy": + if (packageFlags.cluster() || packageFlags.collections() != null) { + deploy( + packageManager, + cmdArgs[0], + packageFlags.cluster(), + packageFlags.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 (packageFlags.cluster() || packageFlags.collections() != null) { + 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"); + } + break; + case "uninstall": + uninstall(packageManager, cmdArgs[0]); + break; + default: + throw new RuntimeException("Unrecognized command: " + command); + } + } + @Override public String getHeader() { StringBuilder sb = new StringBuilder(); @@ -415,6 +541,7 @@ public Options getOptions() { @Override public int callTool() throws Exception { - throw new UnsupportedOperationException("This tool does not yet support PicoCli"); + spec.commandLine().usage(CLIO.getOutStream()); + return 0; } } diff --git a/solr/core/src/java/org/apache/solr/cli/PackageUndeploy.java b/solr/core/src/java/org/apache/solr/cli/PackageUndeploy.java new file mode 100644 index 000000000000..d38da3404070 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageUndeploy.java @@ -0,0 +1,74 @@ +/* + * 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.printRed; + +/** Supports package undeploy 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 PackageUndeploy 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 = + "Specifies that this action should affect plugins for the given collections only, 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/PackageUninstall.java b/solr/core/src/java/org/apache/solr/cli/PackageUninstall.java new file mode 100644 index 000000000000..0171ec552b38 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/cli/PackageUninstall.java @@ -0,0 +1,55 @@ +/* + * 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; + +/** Supports package uninstall 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 PackageUninstall 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"; + } +} 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 6a40ce532db4..555b30bf7c8d 100755 --- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java +++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java @@ -96,7 +96,8 @@ SnapshotDescribeShim.class, SnapshotExportShim.class, SnapshotListShim.class, - RunExampleTool.class + RunExampleTool.class, + PackageTool.class }) public class SolrCLI implements CLIO, java.util.concurrent.Callable { diff --git a/solr/core/src/java/org/apache/solr/pkg/PackageAPI.java b/solr/core/src/java/org/apache/solr/pkg/PackageAPI.java index 0fd1e29dc4a9..4574f7b3318f 100644 --- a/solr/core/src/java/org/apache/solr/pkg/PackageAPI.java +++ b/solr/core/src/java/org/apache/solr/pkg/PackageAPI.java @@ -407,13 +407,11 @@ public void get(SolrQueryRequest req, SolrQueryResponse rsp) { } private void syncToVersion(int expectedVersion) { - int origVersion = pkgs.znodeVersion; for (int i = 0; i < 10; i++) { log.debug("my version is {} , and expected version {}", pkgs.znodeVersion, expectedVersion); if (pkgs.znodeVersion >= expectedVersion) { - if (origVersion < pkgs.znodeVersion) { - packageLoader.refreshPackageConf(); - } + // Blocks until any in-flight refresh started by the ZK watcher has been applied + packageLoader.refreshPackageConf(); return; } try { diff --git a/solr/core/src/java/org/apache/solr/pkg/SolrPackageLoader.java b/solr/core/src/java/org/apache/solr/pkg/SolrPackageLoader.java index 34f6b136eb6c..a512fe77914e 100644 --- a/solr/core/src/java/org/apache/solr/pkg/SolrPackageLoader.java +++ b/solr/core/src/java/org/apache/solr/pkg/SolrPackageLoader.java @@ -80,7 +80,7 @@ public Map getPackages() { return Map.of(); } - public void refreshPackageConf() { + public synchronized void refreshPackageConf() { log.debug( "{} updated to version {}", ZkStateReader.SOLR_PKGS_PATH, packageAPI.pkgs.znodeVersion); @@ -139,7 +139,7 @@ public Map> getModified( return changed; } - public void notifyListeners(String pkg) { + public synchronized void notifyListeners(String pkg) { SolrPackage p = packageClassLoaders.get(pkg); if (p != null) { List l = List.of(p); diff --git a/solr/core/src/test/org/apache/solr/cli/ConnectionOptionsTest.java b/solr/core/src/test/org/apache/solr/cli/ConnectionOptionsTest.java new file mode 100644 index 000000000000..c5b794c1f24d --- /dev/null +++ b/solr/core/src/test/org/apache/solr/cli/ConnectionOptionsTest.java @@ -0,0 +1,46 @@ +/* + * 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.solr.cloud.SolrCloudTestCase; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ConnectionOptionsTest extends SolrCloudTestCase { + + @BeforeClass + public static void setupCluster() throws Exception { + configureCluster(1).configure(); + } + + @Test + public void testResolveZkHostIgnoresEnvWhenSolrUrlProvided() throws Exception { + String solrUrl = cluster.getJettySolrRunner(0).getBaseUrl().toString(); + + System.setProperty("zkHost", "other-cluster:2181/solr"); + System.setProperty("solr.connection", "other-cluster:2181/solr"); + + ConnectionOptions opts = new ConnectionOptions(); + opts.solrUrl = solrUrl; + + String resolved = ConnectionOptions.resolveZkHost(opts, solrUrl, null); + assertNotNull(resolved); + assertFalse( + "HTTP CLI target must not pick up a conflicting zkHost/sys property", + resolved.contains("other-cluster")); + } +} 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..b850ee70cf19 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/cli/PackageToolPicocliTest.java @@ -0,0 +1,32 @@ +/* + * 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..a919b30555b7 100644 --- a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java +++ b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java @@ -68,6 +68,9 @@ public static void setupClusterWithSecurityEnabled() throws Exception { "conf1", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf")) .addConfig( "conf3", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf")) + .addConfig( + "conf-validation", + TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf")) .withSecurityJson(SecurityJson.SIMPLE) .configure(); @@ -89,21 +92,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 +118,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 +133,6 @@ public void testPackageTool() throws Exception { }); run( - tool, new String[] { "--solr-url", solrUrl, "list-installed", "--credentials", SecurityJson.USER_PASS }); @@ -145,7 +145,6 @@ public void testPackageTool() throws Exception { String rhPath = "/mypath2"; run( - tool, new String[] { "--solr-url", solrUrl, @@ -157,7 +156,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 +173,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 +183,6 @@ public void testPackageTool() throws Exception { }); run( - tool, new String[] { "--solr-url", solrUrl, @@ -206,7 +202,6 @@ public void testPackageTool() throws Exception { // This command pegs the version to the latest available run( - tool, new String[] { "--solr-url", solrUrl, @@ -222,7 +217,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 +231,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 +245,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 +261,6 @@ public void testPackageTool() throws Exception { }); } else { run( - tool, new String[] { "--solr-url", solrUrl, @@ -289,7 +280,6 @@ public void testPackageTool() throws Exception { log.info("Running undeploy..."); run( - tool, new String[] { "--solr-url", solrUrl, @@ -302,7 +292,6 @@ public void testPackageTool() throws Exception { }); run( - tool, new String[] { "--solr-url", solrUrl, @@ -378,27 +367,26 @@ public static void testForResponseElement( public void testDeployValidationMessages() throws Exception { String solrUrl = cluster.getJettySolrRunner(0).getBaseUrl().toString(); - withBasicAuth(CollectionAdminRequest.createCollection("validation-test", "conf1", 1, 1)) + withBasicAuth( + CollectionAdminRequest.createCollection("validation-test", "conf-validation", 1, 1)) .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 +397,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 +417,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); } 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 034346e499d6..b001d404ba33 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc @@ -29,6 +29,16 @@ *** xref:cli/solr-delete.adoc[delete] *** xref:cli/solr-export.adoc[export] *** xref:cli/solr-healthcheck.adoc[healthcheck] +*** 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-post.adoc[post] *** xref:cli/solr-postlogs.adoc[postlogs] *** xref:cli/solr-snapshot.adoc[snapshot] 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 4dbe2b5dea4f..318010391d56 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 @@ -68,6 +68,16 @@ Any command not listed here is unavailable when the picocli implementation is en |xref:cli/solr-delete.adoc[bin/solr delete] |xref:cli/solr-export.adoc[bin/solr export] |xref:cli/solr-healthcheck.adoc[bin/solr healthcheck] +|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-post.adoc[bin/solr post] |xref:cli/solr-postlogs.adoc[bin/solr postlogs] |xref:cli/solr-snapshot-create.adoc[bin/solr snapshot create] 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..cd1b181a2a41 --- /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_:: + 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 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 + +_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..ecd8cdfb609d --- /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_:: + The collection to apply the package to, not required. + +*-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..dd61fbb36a0d --- /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_:: + Specifies that this action should affect plugins for the given collections only, 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 new file mode 100644 index 000000000000..ba00cf3e03b3 --- /dev/null +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-package.adoc @@ -0,0 +1,132 @@ +// 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 + +[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 [-hv] [-u=] [-s= | + --solr-url= | -z=] [COMMAND] +.... + +// end::picocli-generated-man-section-synopsis[] + +// 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[] + +// 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-commands[] +== Commands + +xref:cli/solr-package-add-repo.adoc[*add-repo*]:: + Add a package repository to Solr. + +xref:cli/solr-package-add-key.adoc[*add-key*]:: + Add a trusted key to Solr. + +xref:cli/solr-package-list-installed.adoc[*list-installed*]:: + Print a list of packages installed in Solr. + +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. + +// 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/repo + +[%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[]