You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ep...@apache.org on 2023/08/08 12:17:58 UTC
[solr] branch main updated: SOLR-16800: Move towards using the root of Solr as the -solrUrl in the CLI. (#1808)
This is an automated email from the ASF dual-hosted git repository.
epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new 44668dce33f SOLR-16800: Move towards using the root of Solr as the -solrUrl in the CLI. (#1808)
44668dce33f is described below
commit 44668dce33fbde921cc961079d8db29e83f0f9ca
Author: Eric Pugh <ep...@opensourceconnections.com>
AuthorDate: Tue Aug 8 08:17:51 2023 -0400
SOLR-16800: Move towards using the root of Solr as the -solrUrl in the CLI. (#1808)
Now that hostContext can only ever be /solr, and the maturing of the Solr V2 API's that are nested under the /api path, we want Solr commands that take in a -solrUrl to point to the root of your Solr, not a nested path.
This handles this, as well as provides feedback to users who still use the older -solrUrl http://localhost:8983/solr form that they no longer need to do this.
---
solr/CHANGES.txt | 2 +
.../src/java/org/apache/solr/cli/AssertTool.java | 17 ++++--
.../src/java/org/apache/solr/cli/AuthTool.java | 8 +--
.../src/java/org/apache/solr/cli/ConfigTool.java | 5 +-
.../src/java/org/apache/solr/cli/CreateTool.java | 2 +-
.../src/java/org/apache/solr/cli/DeleteTool.java | 2 +-
.../src/java/org/apache/solr/cli/ExportTool.java | 69 +++++++++++-----------
.../src/java/org/apache/solr/cli/PackageTool.java | 23 ++------
.../java/org/apache/solr/cli/RunExampleTool.java | 4 +-
.../core/src/java/org/apache/solr/cli/SolrCLI.java | 54 +++++++++++++----
.../src/java/org/apache/solr/cli/StatusTool.java | 29 ++++-----
.../apache/solr/packagemanager/PackageManager.java | 10 ++--
.../org/apache/solr/cli/HealthcheckToolTest.java | 14 +++++
.../{SolrCliUptimeTest.java => SolrCLITest.java} | 10 +++-
solr/packaging/test/test_assert.bats | 22 +++----
solr/packaging/test/test_config.bats | 2 +-
solr/packaging/test/test_create_collection.bats | 13 +++-
solr/packaging/test/test_delete_collection.bats | 8 +++
solr/packaging/test/test_help.bats | 2 +
solr/packaging/test/test_status.bats | 1 +
.../pages/solr-control-script-reference.adoc | 42 ++++++++++++-
21 files changed, 219 insertions(+), 120 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 6266da0ace7..312c227110e 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -15,6 +15,8 @@ Improvements
* SOLR-16850: Notify a user if they run healthcheck against standalone Solr that it is a SolrCloud only command. (Eric Pugh)
+* SOLR-16800: Solr CLI commands that use -solrUrl now work with a bare url like http://localhost:8983, you no longer need to add the /solr at the end. (Eric Pugh)
+
Optimizations
---------------------
(No changes)
diff --git a/solr/core/src/java/org/apache/solr/cli/AssertTool.java b/solr/core/src/java/org/apache/solr/cli/AssertTool.java
index 014b19d123a..9ece33ccb8d 100644
--- a/solr/core/src/java/org/apache/solr/cli/AssertTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/AssertTool.java
@@ -29,7 +29,6 @@ import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.impl.Http2SolrClient;
import org.apache.solr.client.solrj.request.HealthCheckRequest;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.NamedList;
@@ -198,10 +197,10 @@ public class AssertTool extends ToolBase {
ret += assertSolrNotRunning(cli.getOptionValue("S"));
}
if (cli.hasOption("c")) {
- ret += assertSolrRunningInCloudMode(cli.getOptionValue("c"));
+ ret += assertSolrRunningInCloudMode(SolrCLI.normalizeSolrUrl(cli.getOptionValue("c")));
}
if (cli.hasOption("C")) {
- ret += assertSolrNotRunningInCloudMode(cli.getOptionValue("C"));
+ ret += assertSolrNotRunningInCloudMode(SolrCLI.normalizeSolrUrl(cli.getOptionValue("C")));
}
return ret;
}
@@ -348,11 +347,11 @@ public class AssertTool extends ToolBase {
}
}
- private static int exitOrException(String msg) throws SolrCLI.AssertionFailureException {
+ private static int exitOrException(String msg) throws AssertionFailureException {
if (useExitCode) {
return 1;
} else {
- throw new SolrCLI.AssertionFailureException(message != null ? message : msg);
+ throw new AssertionFailureException(message != null ? message : msg);
}
}
@@ -370,8 +369,14 @@ public class AssertTool extends ToolBase {
}
private static boolean runningSolrIsCloud(String url) throws Exception {
- try (final SolrClient client = new Http2SolrClient.Builder(url).build()) {
+ try (final SolrClient client = SolrCLI.getSolrClient(url)) {
return SolrCLI.isCloudMode(client);
}
}
+
+ public static class AssertionFailureException extends Exception {
+ public AssertionFailureException(String message) {
+ super(message);
+ }
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/cli/AuthTool.java b/solr/core/src/java/org/apache/solr/cli/AuthTool.java
index 8d43af55fdb..a502fa77cef 100644
--- a/solr/core/src/java/org/apache/solr/cli/AuthTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/AuthTool.java
@@ -111,12 +111,8 @@ public class AuthTool extends ToolBase {
.desc(
"This is where any authentication related configuration files, if any, would be placed.")
.build(),
- Option.builder("solrUrl").argName("solrUrl").hasArg().desc("Solr URL.").build(),
- Option.builder("zkHost")
- .argName("zkHost")
- .hasArg()
- .desc("ZooKeeper host to connect to.")
- .build(),
+ SolrCLI.OPTION_SOLRURL,
+ SolrCLI.OPTION_ZKHOST,
SolrCLI.OPTION_VERBOSE);
}
diff --git a/solr/core/src/java/org/apache/solr/cli/ConfigTool.java b/solr/core/src/java/org/apache/solr/cli/ConfigTool.java
index e7a4012e263..5221a28325f 100644
--- a/solr/core/src/java/org/apache/solr/cli/ConfigTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/ConfigTool.java
@@ -24,7 +24,6 @@ import java.util.Map;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.solr.client.solrj.SolrClient;
-import org.apache.solr.client.solrj.impl.Http2SolrClient;
import org.apache.solr.common.util.NamedList;
import org.noggit.CharArr;
import org.noggit.JSONWriter;
@@ -85,7 +84,7 @@ public class ConfigTool extends ToolBase {
@Override
public void runImpl(CommandLine cli) throws Exception {
- String solrUrl = SolrCLI.resolveSolrUrl(cli);
+ String solrUrl = SolrCLI.normalizeSolrUrl(cli);
String action = cli.getOptionValue("action", "set-property");
String collection = cli.getOptionValue("name");
String property = cli.getOptionValue("property");
@@ -109,7 +108,7 @@ public class ConfigTool extends ToolBase {
echo("\nPOSTing request to Config API: " + solrUrl + updatePath);
echo(jsonBody);
- try (SolrClient solrClient = new Http2SolrClient.Builder(solrUrl).build()) {
+ try (SolrClient solrClient = SolrCLI.getSolrClient(solrUrl)) {
NamedList<Object> result = SolrCLI.postJsonToSolr(solrClient, updatePath, jsonBody);
Integer statusCode = (Integer) result.findRecursive("responseHeader", "status");
if (statusCode == 0) {
diff --git a/solr/core/src/java/org/apache/solr/cli/CreateTool.java b/solr/core/src/java/org/apache/solr/cli/CreateTool.java
index e30a30f40bd..9d2f6315469 100644
--- a/solr/core/src/java/org/apache/solr/cli/CreateTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/CreateTool.java
@@ -117,7 +117,7 @@ public class CreateTool extends ToolBase {
@Override
public void runImpl(CommandLine cli) throws Exception {
SolrCLI.raiseLogLevelUnlessVerbose(cli);
- String solrUrl = cli.getOptionValue("solrUrl", SolrCLI.DEFAULT_SOLR_URL);
+ String solrUrl = SolrCLI.normalizeSolrUrl(cli);
try (var solrClient = SolrCLI.getSolrClient(solrUrl)) {
if (SolrCLI.isCloudMode(solrClient)) {
diff --git a/solr/core/src/java/org/apache/solr/cli/DeleteTool.java b/solr/core/src/java/org/apache/solr/cli/DeleteTool.java
index 8d80e029c1c..5e556f02017 100644
--- a/solr/core/src/java/org/apache/solr/cli/DeleteTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/DeleteTool.java
@@ -88,7 +88,7 @@ public class DeleteTool extends ToolBase {
@Override
public void runImpl(CommandLine cli) throws Exception {
SolrCLI.raiseLogLevelUnlessVerbose(cli);
- String solrUrl = cli.getOptionValue("solrUrl", SolrCLI.DEFAULT_SOLR_URL);
+ String solrUrl = SolrCLI.normalizeSolrUrl(cli);
try (var solrClient = SolrCLI.getSolrClient(solrUrl)) {
if (SolrCLI.isCloudMode(solrClient)) {
diff --git a/solr/core/src/java/org/apache/solr/cli/ExportTool.java b/solr/core/src/java/org/apache/solr/cli/ExportTool.java
index c14550fbcd5..9ea5435e071 100644
--- a/solr/core/src/java/org/apache/solr/cli/ExportTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/ExportTool.java
@@ -94,7 +94,39 @@ public class ExportTool extends ToolBase {
@Override
public List<Option> getOptions() {
- return OPTIONS;
+ return List.of(
+ Option.builder("url")
+ .hasArg()
+ .required()
+ .desc("Address of the collection, example http://localhost:8983/solr/gettingstarted.")
+ .build(),
+ Option.builder("out")
+ .hasArg()
+ .required(false)
+ .desc(
+ "Path to output the exported data, and optionally the file name, defaults to 'collection-name'.")
+ .build(),
+ Option.builder("format")
+ .hasArg()
+ .required(false)
+ .desc("Output format for exported docs (json, jsonl or javabin), defaulting to json.")
+ .build(),
+ Option.builder("compress").required(false).desc("Compress the output.").build(),
+ Option.builder("limit")
+ .hasArg()
+ .required(false)
+ .desc("Maximum number of docs to download. Default is 100, use -1 for all docs.")
+ .build(),
+ Option.builder("query")
+ .hasArg()
+ .required(false)
+ .desc("A custom query, default is '*:*'.")
+ .build(),
+ Option.builder("fields")
+ .hasArg()
+ .required(false)
+ .desc("Comma separated list of fields to export. By default all fields are fetched.")
+ .build());
}
public abstract static class Info {
@@ -230,41 +262,6 @@ public class ExportTool extends ToolBase {
void end() throws IOException {}
}
- private static final List<Option> OPTIONS =
- List.of(
- Option.builder("url")
- .hasArg()
- .required()
- .desc("Address of the collection, example http://localhost:8983/solr/gettingstarted.")
- .build(),
- Option.builder("out")
- .hasArg()
- .required(false)
- .desc(
- "Path to output the exported data, and optionally the file name, defaults to 'collection-name'.")
- .build(),
- Option.builder("format")
- .hasArg()
- .required(false)
- .desc("Output format for exported docs (json, jsonl or javabin), defaulting to json.")
- .build(),
- Option.builder("compress").required(false).desc("Compress the output.").build(),
- Option.builder("limit")
- .hasArg()
- .required(false)
- .desc("Maximum number of docs to download. Default is 100, use -1 for all docs.")
- .build(),
- Option.builder("query")
- .hasArg()
- .required(false)
- .desc("A custom query, default is '*:*'.")
- .build(),
- Option.builder("fields")
- .hasArg()
- .required(false)
- .desc("Comma separated list of fields to export. By default all fields are fetched.")
- .build());
-
static class JsonWithLinesSink extends DocsSink {
private final CharArr charArr = new CharArr(1024 * 2);
JSONWriter jsonWriter = new JSONWriter(charArr, -1);
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 6a8714ddb10..97ed80e7be3 100644
--- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java
@@ -60,8 +60,6 @@ public class PackageTool extends ToolBase {
return "package";
}
- public static String solrUrl = null;
- public static String solrBaseUrl = null;
public PackageManager packageManager;
public RepositoryManager repositoryManager;
@@ -79,10 +77,7 @@ public class PackageTool extends ToolBase {
printHelp();
return;
}
-
- solrUrl = cli.getOptionValues("solrUrl")[cli.getOptionValues("solrUrl").length - 1];
- solrBaseUrl = solrUrl.replaceAll("/solr$", ""); // strip out ending "/solr"
- log.info("Solr url:{}, solr base url: {}", solrUrl, solrBaseUrl);
+ String solrUrl = SolrCLI.normalizeSolrUrl(cli);
String zkHost = SolrCLI.getZkHost(cli);
if (zkHost == null) {
throw new SolrException(ErrorCode.INVALID_STATE, "Package manager runs only in SolrCloud");
@@ -90,8 +85,8 @@ public class PackageTool extends ToolBase {
log.info("ZK: {}", zkHost);
- try (SolrClient solrClient = new Http2SolrClient.Builder(solrBaseUrl).build()) {
- packageManager = new PackageManager(solrClient, solrBaseUrl, zkHost);
+ try (SolrClient solrClient = new Http2SolrClient.Builder(solrUrl).build()) {
+ packageManager = new PackageManager(solrClient, solrUrl, zkHost);
try {
repositoryManager = new RepositoryManager(solrClient, packageManager);
@@ -242,7 +237,7 @@ public class PackageTool extends ToolBase {
} catch (Exception ex) {
// We need to print this since SolrCLI drops the stack trace in favour
- // of brevity. Package tool should surely print full stacktraces!
+ // of brevity. Package tool should surely print the full stacktrace!
ex.printStackTrace();
throw ex;
}
@@ -314,15 +309,7 @@ public class PackageTool extends ToolBase {
@Override
public List<Option> getOptions() {
return List.of(
- Option.builder("solrUrl")
- .argName("URL")
- .hasArg()
- .required(true)
- .desc(
- "Address of the Solr Web application, defaults to: "
- + SolrCLI.DEFAULT_SOLR_URL
- + '.')
- .build(),
+ SolrCLI.OPTION_SOLRURL,
Option.builder("collections")
.argName("COLLECTIONS")
.hasArg()
diff --git a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
index 41ddffc0507..80dcdb41c72 100644
--- a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
@@ -400,7 +400,7 @@ public class RunExampleTool extends ToolBase {
+ " }\n");
File filmsJsonFile = new File(exampleDir, "films/films.json");
- String updateUrl = String.format(Locale.ROOT, "%s/%s/update/json", solrUrl, collectionName);
+ String updateUrl = String.format(Locale.ROOT, "%s/%s/update", solrUrl, collectionName);
echo("Indexing films example docs from " + filmsJsonFile.getAbsolutePath());
String[] args =
new String[] {
@@ -410,6 +410,8 @@ public class RunExampleTool extends ToolBase {
updateUrl,
"-type",
"application/json",
+ "-filetypes",
+ "json",
exampleDir.toString()
};
PostTool postTool = new PostTool();
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 c0a385a0198..c3ddd46b85b 100755
--- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
+++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
@@ -75,7 +75,7 @@ public class SolrCLI implements CLIO {
TimeUnit.NANOSECONDS.convert(1, TimeUnit.MINUTES);
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- public static final String DEFAULT_SOLR_URL = "http://localhost:8983/solr";
+ public static final String DEFAULT_SOLR_URL = "http://localhost:8983";
public static final String ZK_HOST = "localhost:9983";
public static final Option OPTION_ZKHOST =
@@ -86,7 +86,8 @@ public class SolrCLI implements CLIO {
.required(false)
.desc(
"Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh; otherwise, defaults to "
- + ZK_HOST)
+ + ZK_HOST
+ + '.')
.longOpt("zkHost")
.build();
public static final Option OPTION_SOLRURL =
@@ -96,7 +97,8 @@ public class SolrCLI implements CLIO {
.required(false)
.desc(
"Base Solr URL, which can be used to determine the zkHost if that's not known; defaults to: "
- + DEFAULT_SOLR_URL)
+ + DEFAULT_SOLR_URL
+ + '.')
.build();
public static final Option OPTION_VERBOSE =
Option.builder("verbose").required(false).desc("Enable more verbose command output.").build();
@@ -382,6 +384,13 @@ public class SolrCLI implements CLIO {
}
public static SolrClient getSolrClient(String solrUrl) {
+ // today we require all urls to end in /solr, however in the future we will need to support the
+ // /api url end point instead.
+ // The /solr/ check is because sometimes a full url is passed in, like
+ // http://localhost:8983/solr/films_shard1_replica_n1/.
+ if (!solrUrl.endsWith("/solr") && !solrUrl.contains("/solr/")) {
+ solrUrl = solrUrl + "/solr";
+ }
return new Http2SolrClient.Builder(solrUrl).withMaxConnectionsPerHost(32).build();
}
@@ -444,11 +453,37 @@ public class SolrCLI implements CLIO {
print("Pass -help or -h after any COMMAND to see command-specific usage information,");
print("such as: ./solr start -help or ./solr stop -h");
}
+
/**
- * Get the base URL of a live Solr instance from either the solrUrl command-line option from
+ * Strips off the end of solrUrl any /solr when a legacy solrUrl like http://localhost:8983/solr
+ * is used, and warns those users. In the future we'll have url's with /api as well.
+ *
+ * @param solrUrl The user supplied url to Solr.
+ * @return the solrUrl in the format that Solr expects to see internally.
+ */
+ public static String normalizeSolrUrl(String solrUrl) {
+ if (solrUrl != null) {
+ if (solrUrl.indexOf("/solr") > -1) { //
+ String newSolrUrl = solrUrl.substring(0, solrUrl.indexOf("/solr"));
+ CLIO.out(
+ "WARNING: URLs provided to this tool needn't include Solr's context-root (e.g. \"/solr\"). Such URLs are deprecated and support for them will be removed in a future release. Correcting from ["
+ + solrUrl
+ + "] to ["
+ + newSolrUrl
+ + "].");
+ solrUrl = newSolrUrl;
+ }
+ if (solrUrl.endsWith("/")) {
+ solrUrl = solrUrl.substring(0, solrUrl.length() - 1);
+ }
+ }
+ return solrUrl;
+ }
+ /**
+ * Get the base URL of a live Solr instance from either the solrUrl command-line option or from
* ZooKeeper.
*/
- public static String resolveSolrUrl(CommandLine cli) throws Exception {
+ public static String normalizeSolrUrl(CommandLine cli) throws Exception {
String solrUrl = cli.getOptionValue("solrUrl");
if (solrUrl == null) {
String zkHost = cli.getOptionValue("zkHost");
@@ -475,6 +510,7 @@ public class SolrCLI implements CLIO {
}
}
}
+ solrUrl = normalizeSolrUrl(solrUrl);
return solrUrl;
}
@@ -488,7 +524,6 @@ public class SolrCLI implements CLIO {
return zkHost;
}
- // find it using the localPort
String solrUrl = cli.getOptionValue("solrUrl");
if (solrUrl == null) {
solrUrl = DEFAULT_SOLR_URL;
@@ -498,6 +533,7 @@ public class SolrCLI implements CLIO {
+ DEFAULT_SOLR_URL
+ ".");
}
+ solrUrl = normalizeSolrUrl(solrUrl);
try (var solrClient = getSolrClient(solrUrl)) {
// hit Solr to get system info
@@ -568,10 +604,4 @@ public class SolrCLI implements CLIO {
solrClient.request(new GenericSolrRequest(SolrRequest.METHOD.GET, SYSTEM_INFO_PATH));
return "solrcloud".equals(systemInfo.get("mode"));
}
-
- public static class AssertionFailureException extends Exception {
- public AssertionFailureException(String message) {
- super(message);
- }
- }
}
diff --git a/solr/core/src/java/org/apache/solr/cli/StatusTool.java b/solr/core/src/java/org/apache/solr/cli/StatusTool.java
index 349804ca7d0..546dc742f3d 100644
--- a/solr/core/src/java/org/apache/solr/cli/StatusTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/StatusTool.java
@@ -57,42 +57,43 @@ public class StatusTool extends ToolBase {
return "status";
}
- // These options are not exposed to the end user, and are
- // used directly by the bin/solr status CLI.
+ public static final Option OPTION_MAXWAITSECS =
+ Option.builder("maxWaitSecs")
+ .argName("SECS")
+ .hasArg()
+ .required(false)
+ .desc("Wait up to the specified number of seconds to see Solr running.")
+ .build();
+
@Override
public List<Option> getOptions() {
return List.of(
- // Unlike most of the other tools, this is an internal, not end user
- // focused setting. Therefore, no default value is provided.
+ // The solrUrl option is not exposed to the end user, and is
+ // created by the bin/solr script and passed into this too.
Option.builder("solrUrl")
.argName("URL")
.hasArg()
.required(false)
.desc("Property set by calling scripts, not meant for user configuration.")
.build(),
- Option.builder("maxWaitSecs")
- .argName("SECS")
- .hasArg()
- .required(false)
- .desc("Wait up to the specified number of seconds to see Solr running.")
- .build());
+ OPTION_MAXWAITSECS);
}
@Override
public void runImpl(CommandLine cli) throws Exception {
- // Override the default help behaviour to put out a customized message that omits the internally
- // focused Options.
+ // Override the default help behaviour to put out a customized message that only list user
+ // settable Options.
if ((cli.getOptions().length == 0 && cli.getArgs().length == 0)
|| cli.hasOption("h")
|| cli.hasOption("help")) {
final Options options = new Options();
- getOptions().forEach(options::addOption);
+ options.addOption(OPTION_MAXWAITSECS);
new HelpFormatter().printHelp("status", options);
return;
}
int maxWaitSecs = Integer.parseInt(cli.getOptionValue("maxWaitSecs", "0"));
- String solrUrl = cli.getOptionValue("solrUrl");
+ String solrUrl = SolrCLI.normalizeSolrUrl(cli);
if (maxWaitSecs > 0) {
int solrPort = (new URL(solrUrl)).getPort();
echo("Waiting up to " + maxWaitSecs + " seconds to see Solr running on port " + solrPort);
diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java
index 5554d0dd022..beefd88653d 100644
--- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java
+++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java
@@ -69,7 +69,7 @@ import org.slf4j.LoggerFactory;
/** Handles most of the management of packages that are already installed in Solr. */
public class PackageManager implements Closeable {
- final String solrBaseUrl;
+ final String solrUrl;
final SolrClient solrClient;
final SolrZkClient zkClient;
@@ -77,8 +77,8 @@ public class PackageManager implements Closeable {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- public PackageManager(SolrClient solrClient, String solrBaseUrl, String zkHost) {
- this.solrBaseUrl = solrBaseUrl;
+ public PackageManager(SolrClient solrClient, String solrUrl, String zkHost) {
+ this.solrUrl = solrUrl;
this.solrClient = solrClient;
this.zkClient =
new SolrZkClient.Builder()
@@ -760,7 +760,7 @@ public class PackageManager implements Closeable {
plugin.name);
String path =
PackageUtils.resolve(cmd.path, pkg.parameterDefaults, overridesMap, systemParams);
- PackageUtils.printGreen("Executing " + solrBaseUrl + path + " for cluster level plugin");
+ PackageUtils.printGreen("Executing " + solrUrl + path + " for cluster level plugin");
if ("GET".equalsIgnoreCase(cmd.method)) {
String response =
@@ -811,7 +811,7 @@ public class PackageManager implements Closeable {
PackageUtils.resolve(
cmd.path, pkg.parameterDefaults, collectionParameterOverrides, systemParams);
PackageUtils.printGreen(
- "Executing " + solrBaseUrl + path + " for collection:" + collection);
+ "Executing " + solrUrl + path + " for collection:" + collection);
if ("GET".equalsIgnoreCase(cmd.method)) {
String response =
diff --git a/solr/core/src/test/org/apache/solr/cli/HealthcheckToolTest.java b/solr/core/src/test/org/apache/solr/cli/HealthcheckToolTest.java
index fd9a4a0c230..a7d8e7150eb 100644
--- a/solr/core/src/test/org/apache/solr/cli/HealthcheckToolTest.java
+++ b/solr/core/src/test/org/apache/solr/cli/HealthcheckToolTest.java
@@ -65,6 +65,20 @@ public class HealthcheckToolTest extends SolrCloudTestCase {
assertEquals(0, runTool(args));
}
+ @Test
+ public void testHealthcheckWithSolrRootUrlParameter() throws Exception {
+
+ Set<String> liveNodes = cluster.getSolrClient().getClusterState().getLiveNodes();
+ String firstLiveNode = liveNodes.iterator().next();
+ String solrUrl =
+ ZkStateReader.from(cluster.getSolrClient()).getBaseUrlForNodeName(firstLiveNode);
+
+ solrUrl = solrUrl.substring(0, solrUrl.indexOf("/solr"));
+
+ String[] args = new String[] {"healthcheck", "-c", "bob", "-solrUrl", solrUrl};
+ assertEquals(0, runTool(args));
+ }
+
private int runTool(String[] args) throws Exception {
Tool tool = findTool(args);
assertTrue(tool instanceof HealthcheckTool);
diff --git a/solr/core/src/test/org/apache/solr/cli/SolrCliUptimeTest.java b/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java
similarity index 75%
rename from solr/core/src/test/org/apache/solr/cli/SolrCliUptimeTest.java
rename to solr/core/src/test/org/apache/solr/cli/SolrCLITest.java
index 4589ea539ef..03f35246211 100644
--- a/solr/core/src/test/org/apache/solr/cli/SolrCliUptimeTest.java
+++ b/solr/core/src/test/org/apache/solr/cli/SolrCLITest.java
@@ -19,7 +19,15 @@ package org.apache.solr.cli;
import org.apache.solr.SolrTestCase;
import org.junit.Test;
-public class SolrCliUptimeTest extends SolrTestCase {
+public class SolrCLITest extends SolrTestCase {
+ @Test
+ public void testResolveSolrUrl() {
+ assertEquals(SolrCLI.normalizeSolrUrl("http://localhost:8983/solr"), "http://localhost:8983");
+ assertEquals(SolrCLI.normalizeSolrUrl("http://localhost:8983/solr/"), "http://localhost:8983");
+ assertEquals(SolrCLI.normalizeSolrUrl("http://localhost:8983/"), "http://localhost:8983");
+ assertEquals(SolrCLI.normalizeSolrUrl("http://localhost:8983"), "http://localhost:8983");
+ }
+
@Test
public void testUptime() {
assertEquals("?", SolrCLI.uptime(0));
diff --git a/solr/packaging/test/test_assert.bats b/solr/packaging/test/test_assert.bats
index 991774add01..66905a39775 100644
--- a/solr/packaging/test/test_assert.bats
+++ b/solr/packaging/test/test_assert.bats
@@ -30,24 +30,26 @@ teardown() {
@test "assert for non cloud mode" {
run solr start
-
+
run solr assert --not-cloud http://localhost:8983/solr
+ assert_output --partial "needn't include Solr's context-root"
refute_output --partial "ERROR"
-
- run solr assert --cloud http://localhost:8983/solr
+
+ run solr assert --cloud http://localhost:8983
assert_output --partial "ERROR: Solr is not running in cloud mode"
-
+
run ! solr assert --cloud http://localhost:8983/solr -e
}
@test "assert for cloud mode" {
- run solr start -c
-
- run solr assert --cloud http://localhost:8983/solr
+ run solr start -c
+
+ run solr assert --cloud http://localhost:8983
refute_output --partial "ERROR"
-
+
run solr assert --not-cloud http://localhost:8983/solr
+ assert_output --partial "needn't include Solr's context-root"
assert_output --partial "ERROR: Solr is not running in standalone mode"
-
- run ! solr assert --not-cloud http://localhost:8983/solr -e
+
+ run ! solr assert --not-cloud http://localhost:8983 -e
}
diff --git a/solr/packaging/test/test_config.bats b/solr/packaging/test/test_config.bats
index b588e0c10db..aff38d25eb9 100644
--- a/solr/packaging/test/test_config.bats
+++ b/solr/packaging/test/test_config.bats
@@ -50,5 +50,5 @@ teardown() {
run solr config -c COLL_NAME -property updateHandler.autoCommit.maxDocs -value 100
assert_output --partial "Successfully set-property updateHandler.autoCommit.maxDocs to 100"
- assert_output --partial "assuming solrUrl is http://localhost:8983/solr"
+ assert_output --partial "assuming solrUrl is http://localhost:8983."
}
diff --git a/solr/packaging/test/test_create_collection.bats b/solr/packaging/test/test_create_collection.bats
index ff776609378..64c90f87087 100644
--- a/solr/packaging/test/test_create_collection.bats
+++ b/solr/packaging/test/test_create_collection.bats
@@ -41,13 +41,20 @@ teardown() {
@test "create collection" {
run solr create -c COLL_NAME
assert_output --partial "Created collection 'COLL_NAME'"
- assert_output --partial "assuming solrUrl is http://localhost:8983/solr"
+ assert_output --partial "assuming solrUrl is http://localhost:8983"
}
@test "create collection using solrUrl" {
+ run solr create -c COLL_NAME -solrUrl http://localhost:8983
+ assert_output --partial "Created collection 'COLL_NAME'"
+ refute_output --partial "assuming solrUrl is http://localhost:8983"
+}
+
+@test "create collection using legacy solrUrl" {
run solr create -c COLL_NAME -solrUrl http://localhost:8983/solr
- assert_output --partial "Created collection 'COLL_NAME'"
- refute_output --partial "assuming solrUrl is http://localhost:8983/solr"
+ assert_output --partial "Created collection 'COLL_NAME'"
+ assert_output --partial "needn't include Solr's context-root"
+ refute_output --partial "assuming solrUrl is http://localhost:8983"
}
@test "create collection using Zookeeper" {
diff --git a/solr/packaging/test/test_delete_collection.bats b/solr/packaging/test/test_delete_collection.bats
index 6e71d1b52ea..bbef50dce10 100644
--- a/solr/packaging/test/test_delete_collection.bats
+++ b/solr/packaging/test/test_delete_collection.bats
@@ -46,6 +46,14 @@ teardown() {
refute collection_exists "COLL_NAME"
}
+@test "can delete collections with solrUrl" {
+ solr create -c "COLL_NAME"
+ assert collection_exists "COLL_NAME"
+
+ solr delete -c "COLL_NAME" -solrUrl http://localhost:8983
+ refute collection_exists "COLL_NAME"
+}
+
@test "collection delete also deletes zk config" {
solr create -c "COLL_NAME"
assert config_exists "COLL_NAME"
diff --git a/solr/packaging/test/test_help.bats b/solr/packaging/test/test_help.bats
index a6a8a497b36..3f929eee351 100644
--- a/solr/packaging/test/test_help.bats
+++ b/solr/packaging/test/test_help.bats
@@ -62,6 +62,8 @@ setup() {
run solr status -help
assert_output --partial 'usage: status'
refute_output --partial 'ERROR'
+ # Make sure custom selection of options for status help works.
+ refute_output --partial '-solrUrl'
}
@test "healthcheck help flag prints help" {
diff --git a/solr/packaging/test/test_status.bats b/solr/packaging/test/test_status.bats
index 64885dc7f52..292de5ca008 100644
--- a/solr/packaging/test/test_status.bats
+++ b/solr/packaging/test/test_status.bats
@@ -43,6 +43,7 @@ teardown() {
@test "status shell script ignores passed in -solrUrl cli parameter from user" {
solr start
run solr status -solrUrl http://localhost:9999/solr
+ assert_output --partial "needn't include Solr's context-root"
assert_output --partial "Found 1 Solr nodes:"
assert_output --partial "running on port 8983"
}
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
index 12e1a4ea0f6..4897a1a2c34 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/solr-control-script-reference.adoc
@@ -553,7 +553,7 @@ Name of the collection to run a healthcheck against.
+
[%autowidth,frame=none]
|===
-|Optional |Default: none
+|Optional |Default: `http://localhost:8983`
|===
+
Base Solr URL, which can be used in SolrCloud mode to determine the ZooKeeper connection string if that's not known.
@@ -710,6 +710,25 @@ It is possible to override this warning with the -force parameter.
+
*Example*: `bin/solr create -c foo -force`
+`-z <zkHost>` or `-zkHost <zkHost>`::
++
+[%autowidth,frame=none]
+|===
+|Optional |Default: `localhost:9983`
+|===
++
+The ZooKeeper connection string, usable in SolrCloud mode.
+Unnecessary if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
+
+`-solrUrl <url>`::
++
+[%autowidth,frame=none]
+|===
+|Optional |Default: `http://localhost:8983`
+|===
++
+Base Solr URL, which can be used in SolrCloud mode to determine the ZooKeeper connection string if that's not known.
+
==== Configuration Directories and SolrCloud
Before creating a collection in SolrCloud, the configuration directory used by the collection must be uploaded to ZooKeeper.
@@ -800,6 +819,25 @@ If the configuration directory is being used by another collection, then it will
+
Skip safety checks when deleting the configuration directory used by a collection.
+`-z <zkHost>` or `-zkHost <zkHost>`::
++
+[%autowidth,frame=none]
+|===
+|Optional |Default: `localhost:9983`
+|===
++
+The ZooKeeper connection string, usable in SolrCloud mode.
+Unnecessary if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
+
+`-solrUrl <url>`::
++
+[%autowidth,frame=none]
+|===
+|Optional |Default: `http://localhost:8983`
+|===
++
+Base Solr URL, which can be used in SolrCloud mode to determine the ZooKeeper connection string if that's not known.
+
== Authentication
The `bin/solr` script allows enabling or disabling Basic Authentication, allowing you to configure authentication from the command line.
@@ -1048,7 +1086,7 @@ Unnecessary if `ZK_HOST` is defined in `solr.in.sh` or `solr.in.cmd`.
+
[%autowidth,frame=none]
|===
-|Optional |Default: `http://localhost:8983/solr`
+|Optional |Default: `http://localhost:8983`
|===
+
Base Solr URL, which can be used in SolrCloud mode to determine the ZooKeeper connection string if that's not known.