diff --git a/changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml b/changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml index bf2d57cb1f34..410b7c408a53 100644 --- a/changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml +++ b/changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml @@ -13,3 +13,5 @@ links: url: https://issues.apache.org/jira/browse/SOLR-17697 - name: SOLR-18510 url: https://issues.apache.org/jira/browse/SOLR-18510 + - name: SOLR-18509 + url: https://issues.apache.org/jira/browse/SOLR-18509 diff --git a/solr/core/src/java/org/apache/solr/cli/ApiTool.java b/solr/core/src/java/org/apache/solr/cli/ApiTool.java index 3f174ed58b81..0f904185bdcb 100644 --- a/solr/core/src/java/org/apache/solr/cli/ApiTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ApiTool.java @@ -31,8 +31,22 @@ * *
Used to send an arbitrary HTTP request to a Solr API endpoint.
*/
+@SuppressWarnings("UnnecessarilyFullyQualified")
+@picocli.CommandLine.Command(
+ name = "api",
+ description = "Used to send an arbitrary HTTP GET request to a Solr API endpoint.",
+ footerHeading = "%nExamples:%n",
+ footer = {
+ " # Send a GET request to a Solr API endpoint",
+ " bin/solr api -s http://localhost:8983/api/collections"
+ })
public class ApiTool extends ToolBase {
+ /**
+ * @deprecated Only used by the commons-cli parser; the picocli path declares this as an annotated
+ * field.
+ */
+ @Deprecated
private static final Option SOLR_URL_OPTION =
Option.builder("s")
.longOpt("solr-url")
@@ -45,6 +59,22 @@ public class ApiTool extends ToolBase {
/** Parameters for the api command, independent of the command line parser. */
record ApiParams(String getUrl, String credentials) {}
+ // --- picocli fields ---
+
+ @picocli.CommandLine.Option(
+ names = {"-s", "--solr-url"},
+ required = true,
+ paramLabel = "URL",
+ description =
+ "Full URL of the Solr API endpoint to GET, e.g. http://localhost:8983/api/collections")
+ private String solrUrlOpt;
+
+ @picocli.CommandLine.Mixin private CredentialsOptions credentialsOptions;
+
+ public ApiTool() {
+ this(new DefaultToolRuntime());
+ }
+
public ApiTool(ToolRuntime runtime) {
super(runtime);
}
@@ -124,6 +154,8 @@ public static ModifiableSolrParams getSolrParamsFromUri(URI uri) {
@Override
public int callTool() throws Exception {
- throw new UnsupportedOperationException("This tool does not yet support PicoCli");
+ ApiParams params = new ApiParams(solrUrlOpt, credentialsOptions.credentials);
+ callApi(params);
+ return 0;
}
}
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 62d3475c9788..998414dd4dda 100755
--- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
+++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
@@ -81,7 +81,8 @@
AuthTool.class,
CreateTool.class,
DeleteTool.class,
- AssertTool.class
+ AssertTool.class,
+ ApiTool.class
})
public class SolrCLI implements CLIO, java.util.concurrent.Callable All {@code @Test} methods are inherited; only the invocation strategy is overridden.
+ */
+public class ApiToolPicocliTest extends ApiToolTest {
+
+ @Override
+ protected int runTool(String[] args, Class extends ToolBase> clazz) throws Exception {
+ // args[0] is the tool name used by commons-cli dispatch; strip it for picocli.
+ String[] toolArgs = Arrays.copyOfRange(args, 1, args.length);
+ ToolRuntime runtime = new CLITestHelper.TestingRuntime(false);
+ ToolBase tool = clazz.getDeclaredConstructor(ToolRuntime.class).newInstance(runtime);
+ return new CommandLine(tool)
+ .setDefaultValueProvider(new CliDefaultValueProvider())
+ .execute(toolArgs);
+ }
+}
diff --git a/solr/core/src/test/org/apache/solr/cli/ApiToolTest.java b/solr/core/src/test/org/apache/solr/cli/ApiToolTest.java
index 6893e51dc227..c44c5258c27d 100644
--- a/solr/core/src/test/org/apache/solr/cli/ApiToolTest.java
+++ b/solr/core/src/test/org/apache/solr/cli/ApiToolTest.java
@@ -32,6 +32,11 @@
public class ApiToolTest extends SolrCloudTestCase {
static String COLLECTION_NAME = "globalLoaderColl";
+ /** Runs the tool. Overridden by the picocli variant of this test. */
+ protected int runTool(String[] args, Class extends ToolBase> clazz) throws Exception {
+ return CLITestHelper.runTool(args, clazz);
+ }
+
@BeforeClass
public static void setupCluster() throws Exception {
configureCluster(1)
@@ -40,6 +45,20 @@ public static void setupCluster() throws Exception {
.configure();
}
+ @Test
+ public void testApiCommandSucceedsOnAnOkResponse() throws Exception {
+ String url = cluster.getJettySolrRunner(0).getBaseUrl() + "/admin/info/system";
+
+ assertEquals(0, runTool(new String[] {"api", "-s", url}, ApiTool.class));
+ }
+
+ @Test
+ public void testApiCommandFailsOnANon2xxResponse() throws Exception {
+ String url = cluster.getJettySolrRunner(0).getBaseUrl() + "/admin/no-such-handler";
+
+ assertEquals(1, runTool(new String[] {"api", "-s", url}, ApiTool.class));
+ }
+
@Test
public void testParsingGetUrl() throws URISyntaxException {
diff --git a/solr/packaging/build.gradle b/solr/packaging/build.gradle
index ccdffbeeaf4d..19c9de386731 100644
--- a/solr/packaging/build.gradle
+++ b/solr/packaging/build.gradle
@@ -364,6 +364,8 @@ task integrationTestsPicocli(type: BatsTask) {
'test/test_delete_collection.bats',
'test/test_zk.bats',
'test/test_auth.bats',
+ 'test/test_modules.bats',
+ 'test/test_security_manager.bats',
]
}
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 53a667155efa..a5c2d787e0b5 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc
@@ -20,6 +20,7 @@
* xref:solr-control-script-reference.adoc[]
** xref:cli/index.adoc[Experimental picocli CLI]
// CLI-DOCS-START
+*** xref:cli/solr-api.adoc[api]
*** xref:cli/solr-assert.adoc[assert]
*** xref:cli/solr-auth.adoc[auth]
*** xref:cli/solr-create.adoc[create]
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 1690291943b8..ed3b6ccda34e 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
@@ -59,6 +59,7 @@ Any command not listed here is unavailable when the picocli implementation is en
|===
|Command
+|xref:cli/solr-api.adoc[bin/solr api]
|xref:cli/solr-assert.adoc[bin/solr assert]
|xref:cli/solr-auth.adoc[bin/solr auth]
|xref:cli/solr-create.adoc[bin/solr create]
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-api.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-api.adoc
new file mode 100644
index 000000000000..cccb38dc9e95
--- /dev/null
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/cli/solr-api.adoc
@@ -0,0 +1,71 @@
+// 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 api
+: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 api [-hv] -s=URL [-u=