From 4c1b39390a1b9049e4915491369cf43e98785854 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 18:41:09 +0530 Subject: [PATCH 01/26] minor --- .../unreleased/SOLR-18234-solr-cli-detangle-core.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml diff --git a/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml b/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml new file mode 100644 index 000000000000..17cc38c4cd8c --- /dev/null +++ b/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml @@ -0,0 +1,9 @@ +title: > + Detangle Outgoing core dependencies to Solr CLI +type: other +authors: + - name: Jalaz Kumar + nick: jaykay12 +links: + - name: SOLR-18234 + url: https://issues.apache.org/jira/browse/SOLR-18234 From d909a9f5b1c391f1aa742e6376d6cc7abb8be5bc Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 19:30:47 +0530 Subject: [PATCH 02/26] first refactoring done --- .../java/org/apache/solr/cli/CLIUtils.java | 12 ++++------ .../java/org/apache/solr/cli/ConfigTool.java | 3 ++- .../org/apache/solr/cli/RunExampleTool.java | 7 +++--- .../src/java/org/apache/solr/cli/SolrCLI.java | 12 ---------- .../solr/packagemanager/PackageManager.java | 23 +++++++++---------- .../solr/packagemanager/PackageUtils.java | 16 +++++++++++++ 6 files changed, 38 insertions(+), 35 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java index 06ed95eae075..b216c074e3d3 100644 --- a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java +++ b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java @@ -46,19 +46,17 @@ import org.apache.solr.common.cloud.SolrZkClient; import org.apache.solr.common.util.EnvUtils; import org.apache.solr.common.util.URLUtil; +import org.apache.solr.packagemanager.PackageUtils; /** Utility class that holds various helper methods for the CLI. */ public final class CLIUtils { private CLIUtils() {} - public static String RED = "\u001B[31m"; - - public static String GREEN = "\u001B[32m"; - - public static String YELLOW = "\u001B[33m"; - - public static String RESET = "\u001B[0m"; + public static String RED = PackageUtils.RED; + public static String GREEN = PackageUtils.GREEN; + public static String YELLOW = PackageUtils.YELLOW; + public static String RESET = PackageUtils.RESET; private static final long MAX_WAIT_FOR_CORE_LOAD_NANOS = TimeUnit.NANOSECONDS.convert(1, TimeUnit.MINUTES); 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 377cd6a44815..f626eef3086d 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConfigTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ConfigTool.java @@ -26,6 +26,7 @@ import org.apache.commons.cli.Options; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.common.util.NamedList; +import org.apache.solr.packagemanager.PackageUtils; import org.noggit.CharArr; import org.noggit.JSONWriter; @@ -149,7 +150,7 @@ void updateConfig(ConfigParams params) throws Exception { echoIfVerbose(jsonBody); try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, params.credentials())) { - NamedList result = SolrCLI.postJsonToSolr(solrClient, updatePath, jsonBody); + NamedList result = PackageUtils.postJsonToSolr(solrClient, updatePath, jsonBody); Integer statusCode = (Integer) result._get(List.of("responseHeader", "status"), null); if (statusCode == 0) { if (value != null) { 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 239a7a163519..f69c60ac8f60 100644 --- a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java +++ b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java @@ -47,6 +47,7 @@ import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.common.SolrException; import org.apache.solr.common.util.EnvUtils; +import org.apache.solr.packagemanager.PackageUtils; import org.noggit.CharArr; import org.noggit.JSONWriter; @@ -489,7 +490,7 @@ void runExample(RunExampleParams params) throws Exception { } else if ("films".equals(exampleName) && !alreadyExists) { try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, params.start().credentials())) { echo("Adding dense vector field type to films schema"); - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, "/" + collectionName + "/schema", """ @@ -506,7 +507,7 @@ void runExample(RunExampleParams params) throws Exception { echo( "Adding name, genre, directed_by, initial_release_date, and film_vector fields to films schema"); - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, "/" + collectionName + "/schema", """ @@ -556,7 +557,7 @@ void runExample(RunExampleParams params) throws Exception { echo( "Adding paramsets \"algo\" and \"algo_b\" to films configuration for relevancy tuning"); - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, "/" + collectionName + "/config/params", """ 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 96ebd09fed90..9c8c26c4199a 100755 --- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java +++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java @@ -42,10 +42,7 @@ import org.apache.commons.cli.help.HelpFormatter; import org.apache.commons.cli.help.TableDefinition; import org.apache.commons.cli.help.TextHelpAppendable; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.request.ContentWriterUpdateRequest; import org.apache.solr.common.util.EnvUtils; -import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SuppressForbidden; import org.apache.solr.util.configuration.SSLConfigurationsFactory; import org.slf4j.Logger; @@ -393,15 +390,6 @@ private static Set findClasses(String path, String packageName) throws E return classes; } - private static final String JSON_CONTENT_TYPE = "application/json"; - - public static NamedList postJsonToSolr( - SolrClient solrClient, String updatePath, String jsonBody) throws Exception { - ContentWriterUpdateRequest req = new ContentWriterUpdateRequest(updatePath); - req.addContentWithType(jsonBody, JSON_CONTENT_TYPE); - return solrClient.request(req); - } - private static final long MS_IN_MIN = 60 * 1000L; private static final long MS_IN_HOUR = MS_IN_MIN * 60L; private static final long MS_IN_DAY = MS_IN_HOUR * 24L; 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 b8c38274f8d1..3bbf07eba117 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java @@ -39,7 +39,6 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import org.apache.solr.cli.CLIUtils; -import org.apache.solr.cli.SolrCLI; import org.apache.solr.cli.ToolRuntime; import org.apache.solr.client.api.util.SolrVersion; import org.apache.solr.client.solrj.SolrClient; @@ -429,7 +428,7 @@ private Pair, List> deployCollectionPackage( .setRequiresCollection( false) /* Making a collection-request, but already baked into path */); boolean packageParamsExist = collectionParams.get("params") != null; - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, PackageUtils.getCollectionParamsPath(collection), getMapper() @@ -445,7 +444,7 @@ private Pair, List> deployCollectionPackage( // Set the package version in the collection's parameters try { - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, PackageUtils.getCollectionParamsPath(collection), "{set:{PKG_VERSIONS:{" @@ -460,7 +459,7 @@ private Pair, List> deployCollectionPackage( // If updating, refresh the package version for this to take effect if (isUpdate || pegToLatest) { try { - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, PackageUtils.PACKAGE_PATH, "{\"refresh\": \"" + packageInstance.name + "\"}"); @@ -503,7 +502,7 @@ private Pair, List> deployCollectionPackage( runtime.printSuccess("Executing " + payload + " for path:" + path); boolean shouldExecute = prompt(noprompt); if (shouldExecute) { - SolrCLI.postJsonToSolr(solrClient, path, payload); + PackageUtils.postJsonToSolr(solrClient, path, payload); } } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, ex); @@ -520,7 +519,7 @@ private Pair, List> deployCollectionPackage( // Set the package version in the collection's parameters try { - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, PackageUtils.getCollectionParamsPath(collection), "{update:{PKG_VERSIONS:{'" @@ -579,7 +578,7 @@ private boolean deployClusterPackage( String postBody = "{\"update\": " + Utils.toJSONString(pluginMeta) + "}"; runtime.printSuccess( "Posting " + postBody + " to " + PackageUtils.CLUSTER_PLUGINS_PATH); - SolrCLI.postJsonToSolr(solrClient, PackageUtils.CLUSTER_PLUGINS_PATH, postBody); + PackageUtils.postJsonToSolr(solrClient, PackageUtils.CLUSTER_PLUGINS_PATH, postBody); } catch (Exception e) { throw new SolrException(ErrorCode.SERVER_ERROR, e); } @@ -652,7 +651,7 @@ private boolean deployClusterPackage( runtime.printSuccess("Executing " + payload + " for path:" + path); boolean shouldExecute = prompt(noprompt); if (shouldExecute) { - SolrCLI.postJsonToSolr(solrClient, path, payload); + PackageUtils.postJsonToSolr(solrClient, path, payload); numberOfClusterPluginsDeployed++; } } catch (Exception ex) { @@ -1001,7 +1000,7 @@ public void undeploy( PackageUtils.resolve( cmd.path, deployedPackage.parameterDefaults, Map.of(), systemParams); runtime.printSuccess("Executing " + payload + " for path:" + path); - SolrCLI.postJsonToSolr(solrClient, path, payload); + PackageUtils.postJsonToSolr(solrClient, path, payload); } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, ex); } @@ -1058,7 +1057,7 @@ public void undeploy( collectionParameterOverrides, systemParams); runtime.printSuccess("Executing " + payload + " for path:" + path); - SolrCLI.postJsonToSolr(solrClient, path, payload); + PackageUtils.postJsonToSolr(solrClient, path, payload); } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, ex); } @@ -1074,11 +1073,11 @@ public void undeploy( // Set the package version in the collection's parameters try { // Is it better to "unset"? If so, build support in params API for "unset" - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, PackageUtils.getCollectionParamsPath(collection), "{set: {PKG_VERSIONS: {" + packageName + ": null}}}"); - SolrCLI.postJsonToSolr( + PackageUtils.postJsonToSolr( solrClient, PackageUtils.PACKAGE_PATH, "{\"refresh\": \"" + packageName + "\"}"); } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, ex); diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java b/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java index c97bdab31236..169731d4aa99 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java @@ -39,6 +39,7 @@ import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.request.ContentWriterUpdateRequest; import org.apache.solr.client.solrj.request.FileStoreApi; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.response.InputStreamResponseParser; @@ -46,6 +47,7 @@ import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.Utils; import org.apache.solr.filestore.ClusterFileStore; import org.apache.solr.filestore.DistribFileStore; @@ -64,6 +66,20 @@ public class PackageUtils { public static String REPOSITORIES_ZK_PATH = "/repositories.json"; public static String CLUSTERPROPS_PATH = "/api/cluster/zk/data/clusterprops.json"; + public static String RED = "\u001B[31m"; + public static String GREEN = "\u001B[32m"; + public static String YELLOW = "\u001B[33m"; + public static String RESET = "\u001B[0m"; + + private static final String JSON_CONTENT_TYPE = "application/json"; + + public static NamedList postJsonToSolr( + SolrClient solrClient, String updatePath, String jsonBody) throws Exception { + ContentWriterUpdateRequest req = new ContentWriterUpdateRequest(updatePath); + req.addContentWithType(jsonBody, JSON_CONTENT_TYPE); + return solrClient.request(req); + } + public static Configuration jsonPathConfiguration() { MappingProvider provider = new JacksonMappingProvider(); JsonProvider jsonProvider = new JacksonJsonProvider(); From 1869143be2bdced93ee83277bc7abe746a6150a7 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 19:37:59 +0530 Subject: [PATCH 03/26] minor --- .../java/org/apache/solr/packagemanager/PackageManager.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 3bbf07eba117..7dce9e761be6 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java @@ -38,7 +38,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import org.apache.solr.cli.CLIUtils; import org.apache.solr.cli.ToolRuntime; import org.apache.solr.client.api.util.SolrVersion; import org.apache.solr.client.solrj.SolrClient; @@ -679,9 +678,9 @@ private boolean prompt(boolean noprompt) { boolean shouldExecute = true; if (!noprompt) { // show a prompt asking user to execute the setup command for the plugin runtime.print( - CLIUtils.YELLOW + PackageUtils.YELLOW + "Execute this command. (If you choose no, you can manually deploy/undeploy this plugin later) (y/n): " - + CLIUtils.RESET); + + PackageUtils.RESET); try (Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8)) { String userInput = scanner.next(); if ("no".trim().equalsIgnoreCase(userInput) || "n".trim().equalsIgnoreCase(userInput)) { From fe4913fd344bdc0a6c3a26d6196ca34e93dffe36 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 19:40:59 +0530 Subject: [PATCH 04/26] minor --- .../java/org/apache/solr/packagemanager/PackageUtils.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java b/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java index 169731d4aa99..67991b8cbec9 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java @@ -34,7 +34,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.apache.commons.io.IOUtils; -import org.apache.solr.cli.CLIUtils; import org.apache.solr.client.api.model.UploadToFileStoreResponse; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -255,7 +254,7 @@ public static String resolve( /** Console print using green color */ public static void formatGreen(StringBuilder sb, Object message) { - format(sb, CLIUtils.GREEN, message); + format(sb, GREEN, message); } public static void format(StringBuilder sb, Object message) { @@ -264,7 +263,7 @@ public static void format(StringBuilder sb, Object message) { public static void format(StringBuilder sb, String color, Object message) { if (color != null) { - sb.append(color + String.valueOf(message) + CLIUtils.RESET + "\n"); + sb.append(color + String.valueOf(message) + RESET + "\n"); } else { sb.append(message + "\n"); } From 469a2bff299b4be07c013d8a28961dd187679643 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 20:18:28 +0530 Subject: [PATCH 05/26] more refactoring --- .../java/org/apache/solr/cli/ToolRuntime.java | 5 ++- .../solr/packagemanager/PackageManager.java | 15 ++++---- .../packagemanager/RepositoryManager.java | 3 +- .../apache/solr/packagemanager/UserIO.java | 34 +++++++++++++++++++ .../packagemanager/TestPackageManager.java | 9 ++--- 5 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/packagemanager/UserIO.java diff --git a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java index dac43d936d0d..b38e45411f57 100644 --- a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java +++ b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java @@ -17,6 +17,7 @@ package org.apache.solr.cli; import org.apache.solr.common.util.SuppressForbidden; +import org.apache.solr.packagemanager.UserIO; /** * An implementation of this class is specified when executing {@link ToolBase} to access @@ -24,18 +25,20 @@ * * @see ToolBase */ -public abstract class ToolRuntime { +public abstract class ToolRuntime implements UserIO { public abstract void print(String message); public abstract void println(String message); /** Print an error message, highlighted in red on terminals. */ + @Override public void printError(String message) { println(CLIUtils.RED + message + CLIUtils.RESET); } /** Print a success message, highlighted in green on terminals. */ + @Override public void printSuccess(String message) { println(CLIUtils.GREEN + message + CLIUtils.RESET); } 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 7dce9e761be6..87fd596bdbe2 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java @@ -38,7 +38,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import org.apache.solr.cli.ToolRuntime; import org.apache.solr.client.api.util.SolrVersion; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -72,7 +71,7 @@ /** Handles most of the management of packages that are already installed in Solr. */ public class PackageManager implements Closeable { - final ToolRuntime runtime; + final UserIO runtime; final String solrUrl; final SolrClient solrClient; final SolrZkClient zkClient; @@ -81,7 +80,7 @@ public class PackageManager implements Closeable { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - public PackageManager(ToolRuntime runtime, SolrClient solrClient, String solrUrl, String zkHost) { + public PackageManager(UserIO runtime, SolrClient solrClient, String solrUrl, String zkHost) { this.runtime = runtime; this.solrUrl = solrUrl; this.solrClient = solrClient; @@ -110,7 +109,7 @@ public void uninstall(String packageName, String version) + ":" + version + " doesn't exist. Use the install command to install this package version first."); - runtime.exit(1); + throw new SolrException(ErrorCode.BAD_REQUEST, ""); } // Make sure that this package instance is not deployed on any collection @@ -123,7 +122,7 @@ public void uninstall(String packageName, String version) + " is currently deployed on collection: " + collection + ". Undeploy the package with undeploy --collections [,,...] before attempting to uninstall the package."); - runtime.exit(1); + throw new SolrException(ErrorCode.BAD_REQUEST, ""); } } @@ -140,7 +139,7 @@ public void uninstall(String packageName, String version) + "is currently deployed as a cluster-level plugin (" + clusterPackageInstance.getCustomData() + "). Undeploy the package with undeploy --collections [,,...] before uninstalling the package."); - runtime.exit(1); + throw new SolrException(ErrorCode.BAD_REQUEST, ""); } } @@ -932,7 +931,7 @@ public void deploy( + ":" + version + ". Use install command to install this version first."); - runtime.exit(1); + throw new SolrException(ErrorCode.BAD_REQUEST, ""); } Manifest manifest = packageInstance.manifest; @@ -942,7 +941,7 @@ public void deploy( + SolrVersion.LATEST + ", package version constraint: " + manifest.versionConstraint); - runtime.exit(1); + throw new SolrException(ErrorCode.BAD_REQUEST, ""); } boolean res = diff --git a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java b/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java index 29a86c75e0ad..d041f7602aa8 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java @@ -36,7 +36,6 @@ import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; -import org.apache.solr.cli.ToolRuntime; import org.apache.solr.client.api.util.SolrVersion; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -67,7 +66,7 @@ public class RepositoryManager { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private final PackageManager packageManager; - private final ToolRuntime runtime; + private final UserIO runtime; final SolrClient solrClient; diff --git a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java new file mode 100644 index 000000000000..fe5dd57e2584 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.packagemanager; + +@FunctionalInterface +public interface UserIO { + + UserIO NONE = message -> {}; + + void print(String message); + + default void printSuccess(String message) { + print(PackageUtils.GREEN + message + PackageUtils.RESET + System.lineSeparator()); + } + + default void printError(String message) { + print(PackageUtils.RED + message + PackageUtils.RESET + System.lineSeparator()); + } +} diff --git a/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java b/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java index 4d6bedf078aa..ba9c97502ee1 100644 --- a/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java +++ b/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java @@ -21,8 +21,6 @@ import java.net.URL; import java.util.List; import java.util.Map; -import org.apache.solr.cli.CLITestHelper; -import org.apache.solr.cli.ToolRuntime; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; @@ -50,8 +48,7 @@ public void testWrongVerificationJPathIsThrown() throws IOException { SolrZkClient zkClient = cluster.getZkClient(); URL baseURLV2 = cluster.getJettySolrRunner(0).getBaseURLV2(); try (var solrClient = new HttpJettySolrClient.Builder(baseURLV2.toString()).build()) { - ToolRuntime runtime = new CLITestHelper.TestingRuntime(false); - try (PackageManager manager = new StubPackageManager(runtime, solrClient, zkClient)) { + try (PackageManager manager = new StubPackageManager(solrClient, zkClient)) { SolrPackage.Plugin plugin = new SolrPackage.Plugin(); if (random().nextBoolean()) { plugin.type = "cluster"; @@ -76,9 +73,9 @@ public void testWrongVerificationJPathIsThrown() throws IOException { } private static class StubPackageManager extends PackageManager { - public StubPackageManager(ToolRuntime runtime, SolrClient solrClient, SolrZkClient zkClient) { + public StubPackageManager(SolrClient solrClient, SolrZkClient zkClient) { super( - runtime, + UserIO.NONE, solrClient, SolrCloudTestCase.cluster.getJettySolrRunners().get(0).getBaseUrl().toString(), zkClient.getZkServerAddress()); From b43ece8bee8e336cbbdbee0c94f20f53f1dcfa30 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 20:20:43 +0530 Subject: [PATCH 06/26] minor --- solr/core/src/java/org/apache/solr/packagemanager/UserIO.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java index fe5dd57e2584..3c67b3f21977 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java @@ -17,6 +17,9 @@ package org.apache.solr.packagemanager; +/** + * Console-facing output for package manager operations + */ @FunctionalInterface public interface UserIO { From 1b65d92327248ae0361510def35fa570e9f58f9b Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 20:47:35 +0530 Subject: [PATCH 07/26] tests refactored --- .../{cloud => cli}/SolrCloudExampleTest.java | 11 ++--------- .../security/BasicAuthIntegrationTest.java | 14 ++++++++------ .../cloud/AbstractFullDistribZkTestBase.java | 19 ++++--------------- 3 files changed, 14 insertions(+), 30 deletions(-) rename solr/core/src/test/org/apache/solr/{cloud => cli}/SolrCloudExampleTest.java (95%) diff --git a/solr/core/src/test/org/apache/solr/cloud/SolrCloudExampleTest.java b/solr/core/src/test/org/apache/solr/cli/SolrCloudExampleTest.java similarity index 95% rename from solr/core/src/test/org/apache/solr/cloud/SolrCloudExampleTest.java rename to solr/core/src/test/org/apache/solr/cli/SolrCloudExampleTest.java index c7a6e70ef295..a9b680c207f9 100644 --- a/solr/core/src/test/org/apache/solr/cloud/SolrCloudExampleTest.java +++ b/solr/core/src/test/org/apache/solr/cli/SolrCloudExampleTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.cloud; +package org.apache.solr.cli; import java.lang.invoke.MethodHandles; import java.nio.file.Files; @@ -23,16 +23,9 @@ import java.util.concurrent.TimeUnit; import org.apache.commons.cli.CommandLine; import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.cli.CLITestHelper; -import org.apache.solr.cli.CLIUtils; -import org.apache.solr.cli.CreateTool; -import org.apache.solr.cli.DeleteTool; -import org.apache.solr.cli.HealthcheckTool; -import org.apache.solr.cli.PostTool; -import org.apache.solr.cli.SolrCLI; -import org.apache.solr.cli.ToolRuntime; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.cloud.AbstractFullDistribZkTestBase; import org.apache.solr.common.cloud.ZkStateReader; import org.apache.solr.util.ExternalPaths; import org.junit.Test; diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java index 71c1da0c463c..0a13381b092e 100644 --- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java @@ -25,16 +25,16 @@ import java.util.Random; import java.util.Set; import java.util.concurrent.TimeUnit; -import org.apache.solr.cli.CLITestHelper; -import org.apache.solr.cli.StatusTool; import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.RequestWriter.StringPayloadContentWriter; +import org.apache.solr.client.solrj.request.SystemInfoRequest; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.client.solrj.request.V2Request; import org.apache.solr.client.solrj.request.beans.PluginMeta; @@ -283,10 +283,12 @@ public void testBasicAuth() throws Exception { verifySecurityStatus(httpClient, baseUrl + "/admin/info/key", "key", NOT_NULL_PREDICATE, 20); assertAuthMetricsMinimums(17, 8, 8, 1, 0, 0); - String[] toolArgs = new String[] {"status", "--solr-url", baseUrl}; - int res = CLITestHelper.runTool(toolArgs, StatusTool.class); - if (res == 0) { - fail("Request should have failed because of missing auth"); + try (SolrClient unauthorizedClient = new HttpJettySolrClient.Builder(baseUrl).build()) { + RemoteSolrException status = expectThrows( + RemoteSolrException.class, + () -> new SystemInfoRequest().process(unauthorizedClient) + ); + assertEquals(401, status.code()); } SolrParams params = new MapSolrParams(Map.of("q", "*:*")); diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java index 0b8e194abc7c..ef6bc6f4c66b 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java @@ -49,10 +49,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import org.apache.solr.BaseDistributedSearchTestCase; -import org.apache.solr.cli.ConfigSetUploadTool; -import org.apache.solr.cli.DefaultToolRuntime; -import org.apache.solr.cli.SolrCLI; -import org.apache.solr.cli.ToolRuntime; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrRequest.METHOD; @@ -2225,18 +2221,11 @@ public static void copyConfigUp( throws Exception { Path fullConfDir = configSetDir.resolve(srcConfigSet); - String[] args = - new String[] { - "--conf-name", dstConfigName, - "--conf-dir", fullConfDir.toAbsolutePath().toString(), - "-z", zkAddr - }; - - ToolRuntime runtime = new DefaultToolRuntime(); - ConfigSetUploadTool tool = new ConfigSetUploadTool(runtime); + try (SolrZkClient zkClient = + new SolrZkClient.Builder().withUrl(zkAddr).withTimeout(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS).build()) { + zkClient.upConfig(fullConfDir, dstConfigName); + } - int res = tool.runTool(SolrCLI.processCommandLineArgs(tool, args)); - assertEquals("Tool should have returned 0 for success, returned: " + res, 0, res); } @Override From 197ae30afdb18c551872f9f9fe1e6c2e7e114be7 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 20:51:47 +0530 Subject: [PATCH 08/26] tidy --- .../src/java/org/apache/solr/packagemanager/UserIO.java | 4 +--- .../org/apache/solr/security/BasicAuthIntegrationTest.java | 7 +++---- .../apache/solr/cloud/AbstractFullDistribZkTestBase.java | 6 ++++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java index 3c67b3f21977..2e26e0b245c7 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java @@ -17,9 +17,7 @@ package org.apache.solr.packagemanager; -/** - * Console-facing output for package manager operations - */ +/** Console-facing output for package manager operations */ @FunctionalInterface public interface UserIO { diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java index 0a13381b092e..a4be70cafc11 100644 --- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java @@ -284,10 +284,9 @@ public void testBasicAuth() throws Exception { assertAuthMetricsMinimums(17, 8, 8, 1, 0, 0); try (SolrClient unauthorizedClient = new HttpJettySolrClient.Builder(baseUrl).build()) { - RemoteSolrException status = expectThrows( - RemoteSolrException.class, - () -> new SystemInfoRequest().process(unauthorizedClient) - ); + RemoteSolrException status = + expectThrows( + RemoteSolrException.class, () -> new SystemInfoRequest().process(unauthorizedClient)); assertEquals(401, status.code()); } diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java index ef6bc6f4c66b..04300caf78d6 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java @@ -2222,10 +2222,12 @@ public static void copyConfigUp( Path fullConfDir = configSetDir.resolve(srcConfigSet); try (SolrZkClient zkClient = - new SolrZkClient.Builder().withUrl(zkAddr).withTimeout(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS).build()) { + new SolrZkClient.Builder() + .withUrl(zkAddr) + .withTimeout(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS) + .build()) { zkClient.upConfig(fullConfDir, dstConfigName); } - } @Override From 0e0b6440a312e0d305feaf2cf7ed553c7f64cd24 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 21:03:38 +0530 Subject: [PATCH 09/26] minor --- .../org/apache/solr/security/BasicAuthIntegrationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java index a4be70cafc11..7ce0630de81e 100644 --- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java @@ -284,10 +284,10 @@ public void testBasicAuth() throws Exception { assertAuthMetricsMinimums(17, 8, 8, 1, 0, 0); try (SolrClient unauthorizedClient = new HttpJettySolrClient.Builder(baseUrl).build()) { - RemoteSolrException status = + RemoteSolrException statusExp = expectThrows( RemoteSolrException.class, () -> new SystemInfoRequest().process(unauthorizedClient)); - assertEquals(401, status.code()); + assertEquals(401, statusExp.code()); } SolrParams params = new MapSolrParams(Map.of("q", "*:*")); From 03cd48f111a7cf4d4e0b988ac0bf7ec8d5db41fb Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 3 Oct 2026 21:24:14 +0530 Subject: [PATCH 10/26] removing unused dependency --- changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml | 4 ++-- solr/test-framework/build.gradle | 1 - solr/test-framework/gradle.lockfile | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml b/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml index 17cc38c4cd8c..1a4b7e65300e 100644 --- a/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml +++ b/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml @@ -1,5 +1,5 @@ -title: > - Detangle Outgoing core dependencies to Solr CLI +title: + Stop PackageManager and test-framework from depending on CLI type: other authors: - name: Jalaz Kumar diff --git a/solr/test-framework/build.gradle b/solr/test-framework/build.gradle index e7338c370426..8f84881de552 100644 --- a/solr/test-framework/build.gradle +++ b/solr/test-framework/build.gradle @@ -60,7 +60,6 @@ dependencies { implementation libs.slf4j.api implementation libs.apache.log4j.api implementation libs.apache.log4j.core - implementation libs.commonscli.commonscli implementation libs.opentelemetry.api implementation(libs.opentelemetry.exporter.prometheus) { transitive = false // most things don't want or already have diff --git a/solr/test-framework/gradle.lockfile b/solr/test-framework/gradle.lockfile index 1cb8d2e82d9b..8fb4c4174f90 100644 --- a/solr/test-framework/gradle.lockfile +++ b/solr/test-framework/gradle.lockfile @@ -32,7 +32,7 @@ com.google.protobuf:protobuf-java:4.36.0=annotationProcessor,errorprone,testAnno com.j256.simplemagic:simplemagic:1.17=jarValidation,runtimeClasspath,testRuntimeClasspath com.jayway.jsonpath:json-path:3.0.0=jarValidation,runtimeClasspath,testRuntimeClasspath com.tdunning:t-digest:3.3=jarValidation,runtimeClasspath,testRuntimeClasspath -commons-cli:commons-cli:1.11.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-cli:commons-cli:1.11.0=jarValidation,runtimeClasspath,testRuntimeClasspath commons-codec:commons-codec:1.22.1=jarValidation,runtimeClasspath,testRuntimeClasspath commons-io:commons-io:2.22.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.dropwizard.metrics:metrics-core:4.2.39=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath From b325308a11a6e242c5757274b34445726619ef10 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 4 Oct 2026 12:33:46 +0530 Subject: [PATCH 11/26] refactor colors to interface --- solr/core/src/java/org/apache/solr/cli/CLIUtils.java | 10 +++++----- .../org/apache/solr/packagemanager/PackageManager.java | 4 ++-- .../org/apache/solr/packagemanager/PackageUtils.java | 9 ++------- .../java/org/apache/solr/packagemanager/UserIO.java | 9 +++++++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java index b216c074e3d3..41ae954100b3 100644 --- a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java +++ b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java @@ -46,17 +46,17 @@ import org.apache.solr.common.cloud.SolrZkClient; import org.apache.solr.common.util.EnvUtils; import org.apache.solr.common.util.URLUtil; -import org.apache.solr.packagemanager.PackageUtils; +import org.apache.solr.packagemanager.UserIO; /** Utility class that holds various helper methods for the CLI. */ public final class CLIUtils { private CLIUtils() {} - public static String RED = PackageUtils.RED; - public static String GREEN = PackageUtils.GREEN; - public static String YELLOW = PackageUtils.YELLOW; - public static String RESET = PackageUtils.RESET; + public static String RED = UserIO.RED; + public static String GREEN = UserIO.GREEN; + public static String YELLOW = UserIO.YELLOW; + public static String RESET = UserIO.RESET; private static final long MAX_WAIT_FOR_CORE_LOAD_NANOS = TimeUnit.NANOSECONDS.convert(1, TimeUnit.MINUTES); 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 87fd596bdbe2..57de10e21d23 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java @@ -677,9 +677,9 @@ private boolean prompt(boolean noprompt) { boolean shouldExecute = true; if (!noprompt) { // show a prompt asking user to execute the setup command for the plugin runtime.print( - PackageUtils.YELLOW + UserIO.YELLOW + "Execute this command. (If you choose no, you can manually deploy/undeploy this plugin later) (y/n): " - + PackageUtils.RESET); + + UserIO.RESET); try (Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8)) { String userInput = scanner.next(); if ("no".trim().equalsIgnoreCase(userInput) || "n".trim().equalsIgnoreCase(userInput)) { diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java b/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java index 67991b8cbec9..adb45717f156 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java @@ -65,11 +65,6 @@ public class PackageUtils { public static String REPOSITORIES_ZK_PATH = "/repositories.json"; public static String CLUSTERPROPS_PATH = "/api/cluster/zk/data/clusterprops.json"; - public static String RED = "\u001B[31m"; - public static String GREEN = "\u001B[32m"; - public static String YELLOW = "\u001B[33m"; - public static String RESET = "\u001B[0m"; - private static final String JSON_CONTENT_TYPE = "application/json"; public static NamedList postJsonToSolr( @@ -254,7 +249,7 @@ public static String resolve( /** Console print using green color */ public static void formatGreen(StringBuilder sb, Object message) { - format(sb, GREEN, message); + format(sb, UserIO.GREEN, message); } public static void format(StringBuilder sb, Object message) { @@ -263,7 +258,7 @@ public static void format(StringBuilder sb, Object message) { public static void format(StringBuilder sb, String color, Object message) { if (color != null) { - sb.append(color + String.valueOf(message) + RESET + "\n"); + sb.append(color + String.valueOf(message) + UserIO.RESET + "\n"); } else { sb.append(message + "\n"); } diff --git a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java index 2e26e0b245c7..89b47a5e3d06 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java @@ -21,15 +21,20 @@ @FunctionalInterface public interface UserIO { + public static String RED = "\u001B[31m"; + public static String GREEN = "\u001B[32m"; + public static String YELLOW = "\u001B[33m"; + public static String RESET = "\u001B[0m"; + UserIO NONE = message -> {}; void print(String message); default void printSuccess(String message) { - print(PackageUtils.GREEN + message + PackageUtils.RESET + System.lineSeparator()); + print(GREEN + message + RESET + System.lineSeparator()); } default void printError(String message) { - print(PackageUtils.RED + message + PackageUtils.RESET + System.lineSeparator()); + print(RED + message + RESET + System.lineSeparator()); } } From 0751fb5881bff405ae11f550492881bdff2e6ef2 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 4 Oct 2026 12:34:16 +0530 Subject: [PATCH 12/26] unused --- solr/core/src/java/org/apache/solr/cli/CLIUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java index 41ae954100b3..a51569854ba7 100644 --- a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java +++ b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java @@ -55,7 +55,6 @@ private CLIUtils() {} public static String RED = UserIO.RED; public static String GREEN = UserIO.GREEN; - public static String YELLOW = UserIO.YELLOW; public static String RESET = UserIO.RESET; private static final long MAX_WAIT_FOR_CORE_LOAD_NANOS = From 71168c05493bd7620e4ec612ffcf999d89b5c3da Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 4 Oct 2026 12:45:47 +0530 Subject: [PATCH 13/26] precommit works --- solr/core/src/java/org/apache/solr/cli/ToolRuntime.java | 1 + 1 file changed, 1 insertion(+) diff --git a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java index b38e45411f57..a8d4ef088e01 100644 --- a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java +++ b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java @@ -27,6 +27,7 @@ */ public abstract class ToolRuntime implements UserIO { + @Override public abstract void print(String message); public abstract void println(String message); From 95ab025e92375133136e32c8f380ab35f6bb671a Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 4 Oct 2026 15:09:15 +0530 Subject: [PATCH 14/26] minor --- solr/core/src/java/org/apache/solr/cli/CLIUtils.java | 11 +++++++---- .../src/java/org/apache/solr/cli/ConfigTool.java | 3 +-- .../src/java/org/apache/solr/cli/RunExampleTool.java | 7 +++---- solr/core/src/java/org/apache/solr/cli/SolrCLI.java | 12 ++++++++++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java index a51569854ba7..06ed95eae075 100644 --- a/solr/core/src/java/org/apache/solr/cli/CLIUtils.java +++ b/solr/core/src/java/org/apache/solr/cli/CLIUtils.java @@ -46,16 +46,19 @@ import org.apache.solr.common.cloud.SolrZkClient; import org.apache.solr.common.util.EnvUtils; import org.apache.solr.common.util.URLUtil; -import org.apache.solr.packagemanager.UserIO; /** Utility class that holds various helper methods for the CLI. */ public final class CLIUtils { private CLIUtils() {} - public static String RED = UserIO.RED; - public static String GREEN = UserIO.GREEN; - public static String RESET = UserIO.RESET; + public static String RED = "\u001B[31m"; + + public static String GREEN = "\u001B[32m"; + + public static String YELLOW = "\u001B[33m"; + + public static String RESET = "\u001B[0m"; private static final long MAX_WAIT_FOR_CORE_LOAD_NANOS = TimeUnit.NANOSECONDS.convert(1, TimeUnit.MINUTES); 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 f626eef3086d..377cd6a44815 100644 --- a/solr/core/src/java/org/apache/solr/cli/ConfigTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ConfigTool.java @@ -26,7 +26,6 @@ import org.apache.commons.cli.Options; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.common.util.NamedList; -import org.apache.solr.packagemanager.PackageUtils; import org.noggit.CharArr; import org.noggit.JSONWriter; @@ -150,7 +149,7 @@ void updateConfig(ConfigParams params) throws Exception { echoIfVerbose(jsonBody); try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, params.credentials())) { - NamedList result = PackageUtils.postJsonToSolr(solrClient, updatePath, jsonBody); + NamedList result = SolrCLI.postJsonToSolr(solrClient, updatePath, jsonBody); Integer statusCode = (Integer) result._get(List.of("responseHeader", "status"), null); if (statusCode == 0) { if (value != null) { 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 f69c60ac8f60..239a7a163519 100644 --- a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java +++ b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java @@ -47,7 +47,6 @@ import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.common.SolrException; import org.apache.solr.common.util.EnvUtils; -import org.apache.solr.packagemanager.PackageUtils; import org.noggit.CharArr; import org.noggit.JSONWriter; @@ -490,7 +489,7 @@ void runExample(RunExampleParams params) throws Exception { } else if ("films".equals(exampleName) && !alreadyExists) { try (SolrClient solrClient = CLIUtils.getSolrClient(solrUrl, params.start().credentials())) { echo("Adding dense vector field type to films schema"); - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, "/" + collectionName + "/schema", """ @@ -507,7 +506,7 @@ void runExample(RunExampleParams params) throws Exception { echo( "Adding name, genre, directed_by, initial_release_date, and film_vector fields to films schema"); - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, "/" + collectionName + "/schema", """ @@ -557,7 +556,7 @@ void runExample(RunExampleParams params) throws Exception { echo( "Adding paramsets \"algo\" and \"algo_b\" to films configuration for relevancy tuning"); - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, "/" + collectionName + "/config/params", """ 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 9c8c26c4199a..96ebd09fed90 100755 --- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java +++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java @@ -42,7 +42,10 @@ import org.apache.commons.cli.help.HelpFormatter; import org.apache.commons.cli.help.TableDefinition; import org.apache.commons.cli.help.TextHelpAppendable; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.request.ContentWriterUpdateRequest; import org.apache.solr.common.util.EnvUtils; +import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SuppressForbidden; import org.apache.solr.util.configuration.SSLConfigurationsFactory; import org.slf4j.Logger; @@ -390,6 +393,15 @@ private static Set findClasses(String path, String packageName) throws E return classes; } + private static final String JSON_CONTENT_TYPE = "application/json"; + + public static NamedList postJsonToSolr( + SolrClient solrClient, String updatePath, String jsonBody) throws Exception { + ContentWriterUpdateRequest req = new ContentWriterUpdateRequest(updatePath); + req.addContentWithType(jsonBody, JSON_CONTENT_TYPE); + return solrClient.request(req); + } + private static final long MS_IN_MIN = 60 * 1000L; private static final long MS_IN_HOUR = MS_IN_MIN * 60L; private static final long MS_IN_DAY = MS_IN_HOUR * 24L; From 1aa3fec15b916f438ca7fb28bd0bce102f6dc2a9 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 4 Oct 2026 15:18:43 +0530 Subject: [PATCH 15/26] made package private & non-static --- .../src/java/org/apache/solr/packagemanager/UserIO.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java index 89b47a5e3d06..81997337f1e2 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java @@ -21,10 +21,10 @@ @FunctionalInterface public interface UserIO { - public static String RED = "\u001B[31m"; - public static String GREEN = "\u001B[32m"; - public static String YELLOW = "\u001B[33m"; - public static String RESET = "\u001B[0m"; + String RED = "\u001B[31m"; + String GREEN = "\u001B[32m"; + String YELLOW = "\u001B[33m"; + String RESET = "\u001B[0m"; UserIO NONE = message -> {}; From fbe2fff5fe984026fcb4d5b138d8dd56d8167577 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 4 Oct 2026 15:38:39 +0530 Subject: [PATCH 16/26] ai review --- .../solr/packagemanager/PackageManager.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) 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 57de10e21d23..81adf4a269ed 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java @@ -99,30 +99,33 @@ public void close() throws IOException { } } + private void fail(String message) { + runtime.printError(message); + throw new SolrException(ErrorCode.BAD_REQUEST, message); + } + public void uninstall(String packageName, String version) throws IOException, SolrServerException { SolrPackageInstance packageInstance = getPackageInstance(packageName, version); if (packageInstance == null) { - runtime.printError( + fail( "Package " + packageName + ":" + version + " doesn't exist. Use the install command to install this package version first."); - throw new SolrException(ErrorCode.BAD_REQUEST, ""); } // Make sure that this package instance is not deployed on any collection Map collectionsDeployedOn = getDeployedCollections(packageName); for (String collection : collectionsDeployedOn.keySet()) { if (version.equals(collectionsDeployedOn.get(collection))) { - runtime.printError( + fail( "Package " + packageName + " is currently deployed on collection: " + collection + ". Undeploy the package with undeploy --collections [,,...] before attempting to uninstall the package."); - throw new SolrException(ErrorCode.BAD_REQUEST, ""); } } @@ -133,13 +136,12 @@ public void uninstall(String packageName, String version) SolrPackageInstance clusterPackageInstance = clusterPackages.get(clusterPackageName); if (packageName.equals(clusterPackageName) && version.equals(clusterPackageInstance.version)) { - runtime.printError( + fail( "Package " + packageName + "is currently deployed as a cluster-level plugin (" + clusterPackageInstance.getCustomData() + "). Undeploy the package with undeploy --collections [,,...] before uninstalling the package."); - throw new SolrException(ErrorCode.BAD_REQUEST, ""); } } @@ -925,18 +927,17 @@ public void deploy( boolean pegToLatest = PackageUtils.LATEST.equals(version); SolrPackageInstance packageInstance = getPackageInstance(packageName, version); if (packageInstance == null) { - runtime.printError( + fail( "Package instance doesn't exist: " + packageName + ":" + version + ". Use install command to install this version first."); - throw new SolrException(ErrorCode.BAD_REQUEST, ""); } Manifest manifest = packageInstance.manifest; if (!SolrVersion.LATEST.satisfies(manifest.versionConstraint)) { - runtime.printError( + fail( "Version incompatible! Solr version: " + SolrVersion.LATEST + ", package version constraint: " From e0c79f7b7e3fab70008ea6215e544fe99f38cfe1 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 4 Oct 2026 15:40:16 +0530 Subject: [PATCH 17/26] minor removal --- .../src/java/org/apache/solr/packagemanager/PackageManager.java | 1 - 1 file changed, 1 deletion(-) 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 81adf4a269ed..bc39de8dd80d 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java @@ -942,7 +942,6 @@ public void deploy( + SolrVersion.LATEST + ", package version constraint: " + manifest.versionConstraint); - throw new SolrException(ErrorCode.BAD_REQUEST, ""); } boolean res = From 8706d2ba44e614f7e88c00494a3411f91403246f Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 5 Oct 2026 09:39:34 +0530 Subject: [PATCH 18/26] refactored out pm to cli package --- .../java/org/apache/solr/cli/PackageTool.java | 16 ++++++++-------- .../java/org/apache/solr/cli/ToolRuntime.java | 2 +- .../src/java/org/apache/solr/cli/ZkCpTool.java | 2 +- .../java/org/apache/solr/cli/ZkMkrootTool.java | 2 +- .../src/java/org/apache/solr/cli/ZkMvTool.java | 2 +- .../packagemanager/DefaultPackageRepository.java | 2 +- .../{ => cli}/packagemanager/PackageManager.java | 10 +++++----- .../packagemanager/PackageRepository.java | 2 +- .../{ => cli}/packagemanager/PackageUtils.java | 4 ++-- .../packagemanager/RepositoryManager.java | 8 ++++---- .../{ => cli}/packagemanager/SolrPackage.java | 2 +- .../packagemanager/SolrPackageInstance.java | 6 +++--- .../solr/{ => cli}/packagemanager/UserIO.java | 2 +- .../{ => cli}/packagemanager/package-info.java | 2 +- .../solr/filestore/TestDistribFileStore.java | 2 +- .../solr/packagemanager/TestPackageManager.java | 4 ++++ 16 files changed, 36 insertions(+), 32 deletions(-) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/DefaultPackageRepository.java (98%) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/PackageManager.java (99%) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/PackageRepository.java (97%) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/PackageUtils.java (99%) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/RepositoryManager.java (98%) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/SolrPackage.java (98%) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/SolrPackageInstance.java (93%) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/UserIO.java (96%) rename solr/core/src/java/org/apache/solr/{ => cli}/packagemanager/package-info.java (95%) 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 72b1c1ed8c4e..419009385a6e 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -18,8 +18,8 @@ import static org.apache.solr.cli.SolrCLI.printGreen; import static org.apache.solr.cli.SolrCLI.printRed; -import static org.apache.solr.packagemanager.PackageUtils.format; -import static org.apache.solr.packagemanager.PackageUtils.formatGreen; +import static org.apache.solr.cli.packagemanager.PackageUtils.format; +import static org.apache.solr.cli.packagemanager.PackageUtils.formatGreen; import java.lang.invoke.MethodHandles; import java.nio.file.Files; @@ -36,12 +36,12 @@ import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.util.Pair; -import org.apache.solr.packagemanager.PackageManager; -import org.apache.solr.packagemanager.PackageUtils; -import org.apache.solr.packagemanager.RepositoryManager; -import org.apache.solr.packagemanager.SolrPackage; -import org.apache.solr.packagemanager.SolrPackage.SolrPackageRelease; -import org.apache.solr.packagemanager.SolrPackageInstance; +import org.apache.solr.cli.packagemanager.PackageManager; +import org.apache.solr.cli.packagemanager.PackageUtils; +import org.apache.solr.cli.packagemanager.RepositoryManager; +import org.apache.solr.cli.packagemanager.SolrPackage; +import org.apache.solr.cli.packagemanager.SolrPackage.SolrPackageRelease; +import org.apache.solr.cli.packagemanager.SolrPackageInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java index a8d4ef088e01..c3e1828154bf 100644 --- a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java +++ b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java @@ -17,7 +17,7 @@ package org.apache.solr.cli; import org.apache.solr.common.util.SuppressForbidden; -import org.apache.solr.packagemanager.UserIO; +import org.apache.solr.cli.packagemanager.UserIO; /** * An implementation of this class is specified when executing {@link ToolBase} to access diff --git a/solr/core/src/java/org/apache/solr/cli/ZkCpTool.java b/solr/core/src/java/org/apache/solr/cli/ZkCpTool.java index 2edaccee9df1..1cb760aa952b 100644 --- a/solr/core/src/java/org/apache/solr/cli/ZkCpTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ZkCpTool.java @@ -16,7 +16,7 @@ */ package org.apache.solr.cli; -import static org.apache.solr.packagemanager.PackageUtils.format; +import static org.apache.solr.cli.packagemanager.PackageUtils.format; import java.lang.invoke.MethodHandles; import java.lang.reflect.InvocationTargetException; diff --git a/solr/core/src/java/org/apache/solr/cli/ZkMkrootTool.java b/solr/core/src/java/org/apache/solr/cli/ZkMkrootTool.java index 2a644f2a1364..5bd0cccd329d 100644 --- a/solr/core/src/java/org/apache/solr/cli/ZkMkrootTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ZkMkrootTool.java @@ -16,7 +16,7 @@ */ package org.apache.solr.cli; -import static org.apache.solr.packagemanager.PackageUtils.format; +import static org.apache.solr.cli.packagemanager.PackageUtils.format; import java.lang.invoke.MethodHandles; import org.apache.commons.cli.CommandLine; diff --git a/solr/core/src/java/org/apache/solr/cli/ZkMvTool.java b/solr/core/src/java/org/apache/solr/cli/ZkMvTool.java index a11ac0884f87..936821b1dc89 100644 --- a/solr/core/src/java/org/apache/solr/cli/ZkMvTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ZkMvTool.java @@ -16,7 +16,7 @@ */ package org.apache.solr.cli; -import static org.apache.solr.packagemanager.PackageUtils.format; +import static org.apache.solr.cli.packagemanager.PackageUtils.format; import java.lang.invoke.MethodHandles; import java.util.Locale; diff --git a/solr/core/src/java/org/apache/solr/packagemanager/DefaultPackageRepository.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/DefaultPackageRepository.java similarity index 98% rename from solr/core/src/java/org/apache/solr/packagemanager/DefaultPackageRepository.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/DefaultPackageRepository.java index 8fbbfbbd3477..2cf7416ae273 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/DefaultPackageRepository.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/DefaultPackageRepository.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.type.TypeReference; diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java similarity index 99% rename from solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java index bc39de8dd80d..67630d20ee9b 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; -import static org.apache.solr.packagemanager.PackageUtils.getMapper; +import static org.apache.solr.cli.packagemanager.PackageUtils.getMapper; import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.JsonPath; @@ -60,9 +60,9 @@ import org.apache.solr.common.util.Utils; import org.apache.solr.filestore.DistribFileStore; import org.apache.solr.handler.admin.ContainerPluginsApi; -import org.apache.solr.packagemanager.SolrPackage.Command; -import org.apache.solr.packagemanager.SolrPackage.Manifest; -import org.apache.solr.packagemanager.SolrPackage.Plugin; +import org.apache.solr.cli.packagemanager.SolrPackage.Command; +import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; +import org.apache.solr.cli.packagemanager.SolrPackage.Plugin; import org.apache.solr.pkg.SolrPackageLoader; import org.apache.zookeeper.KeeperException; import org.slf4j.Logger; diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageRepository.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageRepository.java similarity index 97% rename from solr/core/src/java/org/apache/solr/packagemanager/PackageRepository.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/PackageRepository.java index e791a49e5420..2586ee600d69 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageRepository.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageRepository.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; import java.io.IOException; import java.nio.file.Path; diff --git a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java similarity index 99% rename from solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java index adb45717f156..53aa7b8cb3ad 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/PackageUtils.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; import static org.apache.solr.client.solrj.util.SolrIdentifierValidator.validateCollectionName; @@ -51,7 +51,7 @@ import org.apache.solr.filestore.ClusterFileStore; import org.apache.solr.filestore.DistribFileStore; import org.apache.solr.filestore.FileStoreAPI; -import org.apache.solr.packagemanager.SolrPackage.Manifest; +import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; import org.apache.solr.util.SolrJacksonAnnotationInspector; import org.apache.zookeeper.server.ByteBufferInputStream; diff --git a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java similarity index 98% rename from solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java index d041f7602aa8..eb9fc7070c30 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java @@ -15,9 +15,9 @@ * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; -import static org.apache.solr.packagemanager.PackageUtils.getMapper; +import static org.apache.solr.cli.packagemanager.PackageUtils.getMapper; import java.io.IOException; import java.io.InputStream; @@ -52,8 +52,8 @@ import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.Utils; import org.apache.solr.filestore.ClusterFileStore; -import org.apache.solr.packagemanager.SolrPackage.Artifact; -import org.apache.solr.packagemanager.SolrPackage.SolrPackageRelease; +import org.apache.solr.cli.packagemanager.SolrPackage.Artifact; +import org.apache.solr.cli.packagemanager.SolrPackage.SolrPackageRelease; import org.apache.solr.pkg.PackageAPI; import org.apache.solr.pkg.SolrPackageLoader; import org.apache.zookeeper.KeeperException; diff --git a/solr/core/src/java/org/apache/solr/packagemanager/SolrPackage.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackage.java similarity index 98% rename from solr/core/src/java/org/apache/solr/packagemanager/SolrPackage.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackage.java index 750a23d21621..f57c5713dd2e 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/SolrPackage.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackage.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; import java.util.Date; import java.util.List; diff --git a/solr/core/src/java/org/apache/solr/packagemanager/SolrPackageInstance.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackageInstance.java similarity index 93% rename from solr/core/src/java/org/apache/solr/packagemanager/SolrPackageInstance.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackageInstance.java index fd94bc8572f7..423ec107fcfa 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/SolrPackageInstance.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackageInstance.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.List; @@ -23,8 +23,8 @@ import java.util.Objects; import org.apache.solr.common.annotation.JsonProperty; import org.apache.solr.common.util.ReflectMapWriter; -import org.apache.solr.packagemanager.SolrPackage.Manifest; -import org.apache.solr.packagemanager.SolrPackage.Plugin; +import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; +import org.apache.solr.cli.packagemanager.SolrPackage.Plugin; /** Describes one instance of a package as it exists in Solr when installed. */ public class SolrPackageInstance implements ReflectMapWriter { diff --git a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/UserIO.java similarity index 96% rename from solr/core/src/java/org/apache/solr/packagemanager/UserIO.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/UserIO.java index 81997337f1e2..e00aae2cab4f 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/UserIO.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/UserIO.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; /** Console-facing output for package manager operations */ @FunctionalInterface diff --git a/solr/core/src/java/org/apache/solr/packagemanager/package-info.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/package-info.java similarity index 95% rename from solr/core/src/java/org/apache/solr/packagemanager/package-info.java rename to solr/core/src/java/org/apache/solr/cli/packagemanager/package-info.java index 1fa175dec4be..0a42a28f435e 100644 --- a/solr/core/src/java/org/apache/solr/packagemanager/package-info.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/package-info.java @@ -16,4 +16,4 @@ */ /** This package contains Package Manager (CLI) implementation */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; diff --git a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java index 133116e6908b..6c98aac81888 100644 --- a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java +++ b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java @@ -50,7 +50,7 @@ import org.apache.solr.common.util.SuppressForbidden; import org.apache.solr.common.util.Utils; import org.apache.solr.embedded.JettySolrRunner; -import org.apache.solr.packagemanager.PackageUtils; +import org.apache.solr.cli.packagemanager.PackageUtils; import org.apache.solr.util.LogLevel; import org.apache.zookeeper.server.ByteBufferInputStream; import org.junit.Before; diff --git a/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java b/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java index ba9c97502ee1..1820cc14f6bf 100644 --- a/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java +++ b/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java @@ -21,6 +21,10 @@ import java.net.URL; import java.util.List; import java.util.Map; +import org.apache.solr.cli.packagemanager.PackageManager; +import org.apache.solr.cli.packagemanager.SolrPackage; +import org.apache.solr.cli.packagemanager.SolrPackageInstance; +import org.apache.solr.cli.packagemanager.UserIO; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; From 1725692d68b7e21682635541ffde3dbc541c61d6 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 5 Oct 2026 09:44:59 +0530 Subject: [PATCH 19/26] refactoring & tidy --- solr/core/src/java/org/apache/solr/cli/PackageTool.java | 8 ++++---- solr/core/src/java/org/apache/solr/cli/ToolRuntime.java | 2 +- .../apache/solr/cli/packagemanager/PackageManager.java | 6 +++--- .../org/apache/solr/cli/packagemanager/PackageUtils.java | 2 +- .../apache/solr/cli/packagemanager/RepositoryManager.java | 4 ++-- .../solr/cli/packagemanager/SolrPackageInstance.java | 4 ++-- .../solr/{ => cli}/packagemanager/TestPackageManager.java | 6 +----- .../org/apache/solr/filestore/TestDistribFileStore.java | 2 +- 8 files changed, 15 insertions(+), 19 deletions(-) rename solr/core/src/test/org/apache/solr/{ => cli}/packagemanager/TestPackageManager.java (92%) 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 419009385a6e..92ca6e421b7b 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageTool.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageTool.java @@ -32,16 +32,16 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configurator; import org.apache.lucene.util.SuppressForbidden; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.SolrException.ErrorCode; -import org.apache.solr.common.util.Pair; import org.apache.solr.cli.packagemanager.PackageManager; import org.apache.solr.cli.packagemanager.PackageUtils; import org.apache.solr.cli.packagemanager.RepositoryManager; import org.apache.solr.cli.packagemanager.SolrPackage; import org.apache.solr.cli.packagemanager.SolrPackage.SolrPackageRelease; import org.apache.solr.cli.packagemanager.SolrPackageInstance; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.SolrException.ErrorCode; +import org.apache.solr.common.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java index c3e1828154bf..b33352664fab 100644 --- a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java +++ b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java @@ -16,8 +16,8 @@ */ package org.apache.solr.cli; -import org.apache.solr.common.util.SuppressForbidden; import org.apache.solr.cli.packagemanager.UserIO; +import org.apache.solr.common.util.SuppressForbidden; /** * An implementation of this class is specified when executing {@link ToolBase} to access diff --git a/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java index 67630d20ee9b..ae1717332a80 100644 --- a/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java @@ -38,6 +38,9 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import org.apache.solr.cli.packagemanager.SolrPackage.Command; +import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; +import org.apache.solr.cli.packagemanager.SolrPackage.Plugin; import org.apache.solr.client.api.util.SolrVersion; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -60,9 +63,6 @@ import org.apache.solr.common.util.Utils; import org.apache.solr.filestore.DistribFileStore; import org.apache.solr.handler.admin.ContainerPluginsApi; -import org.apache.solr.cli.packagemanager.SolrPackage.Command; -import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; -import org.apache.solr.cli.packagemanager.SolrPackage.Plugin; import org.apache.solr.pkg.SolrPackageLoader; import org.apache.zookeeper.KeeperException; import org.slf4j.Logger; diff --git a/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java index 53aa7b8cb3ad..cdbc1b040257 100644 --- a/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java @@ -34,6 +34,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.apache.commons.io.IOUtils; +import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; import org.apache.solr.client.api.model.UploadToFileStoreResponse; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -51,7 +52,6 @@ import org.apache.solr.filestore.ClusterFileStore; import org.apache.solr.filestore.DistribFileStore; import org.apache.solr.filestore.FileStoreAPI; -import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; import org.apache.solr.util.SolrJacksonAnnotationInspector; import org.apache.zookeeper.server.ByteBufferInputStream; diff --git a/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java index eb9fc7070c30..0da8b2444c53 100644 --- a/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java @@ -36,6 +36,8 @@ import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; +import org.apache.solr.cli.packagemanager.SolrPackage.Artifact; +import org.apache.solr.cli.packagemanager.SolrPackage.SolrPackageRelease; import org.apache.solr.client.api.util.SolrVersion; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -52,8 +54,6 @@ import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.Utils; import org.apache.solr.filestore.ClusterFileStore; -import org.apache.solr.cli.packagemanager.SolrPackage.Artifact; -import org.apache.solr.cli.packagemanager.SolrPackage.SolrPackageRelease; import org.apache.solr.pkg.PackageAPI; import org.apache.solr.pkg.SolrPackageLoader; import org.apache.zookeeper.KeeperException; diff --git a/solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackageInstance.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackageInstance.java index 423ec107fcfa..040de2babc4b 100644 --- a/solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackageInstance.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/SolrPackageInstance.java @@ -21,10 +21,10 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import org.apache.solr.common.annotation.JsonProperty; -import org.apache.solr.common.util.ReflectMapWriter; import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; import org.apache.solr.cli.packagemanager.SolrPackage.Plugin; +import org.apache.solr.common.annotation.JsonProperty; +import org.apache.solr.common.util.ReflectMapWriter; /** Describes one instance of a package as it exists in Solr when installed. */ public class SolrPackageInstance implements ReflectMapWriter { diff --git a/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java b/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java similarity index 92% rename from solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java rename to solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java index 1820cc14f6bf..504db7b263bb 100644 --- a/solr/core/src/test/org/apache/solr/packagemanager/TestPackageManager.java +++ b/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java @@ -14,17 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.packagemanager; +package org.apache.solr.cli.packagemanager; import com.jayway.jsonpath.InvalidPathException; import java.io.IOException; import java.net.URL; import java.util.List; import java.util.Map; -import org.apache.solr.cli.packagemanager.PackageManager; -import org.apache.solr.cli.packagemanager.SolrPackage; -import org.apache.solr.cli.packagemanager.SolrPackageInstance; -import org.apache.solr.cli.packagemanager.UserIO; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; diff --git a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java index 6c98aac81888..4d1ef7b6b7ac 100644 --- a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java +++ b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java @@ -32,6 +32,7 @@ import java.util.concurrent.Callable; import java.util.function.Predicate; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.solr.cli.packagemanager.PackageUtils; import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -50,7 +51,6 @@ import org.apache.solr.common.util.SuppressForbidden; import org.apache.solr.common.util.Utils; import org.apache.solr.embedded.JettySolrRunner; -import org.apache.solr.cli.packagemanager.PackageUtils; import org.apache.solr.util.LogLevel; import org.apache.zookeeper.server.ByteBufferInputStream; import org.junit.Before; From 86d3ec5081f3d030de4b79e368c693023c2c3be8 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 5 Oct 2026 09:58:46 +0530 Subject: [PATCH 20/26] cleanup --- .../java/org/apache/solr/cli/ToolRuntime.java | 6 +-- .../cli/packagemanager/PackageManager.java | 53 ++++++++++--------- .../solr/cli/packagemanager/PackageUtils.java | 16 ++---- .../cli/packagemanager/RepositoryManager.java | 3 +- .../solr/cli/packagemanager/UserIO.java | 40 -------------- .../packagemanager/TestPackageManager.java | 9 ++-- 6 files changed, 40 insertions(+), 87 deletions(-) delete mode 100644 solr/core/src/java/org/apache/solr/cli/packagemanager/UserIO.java diff --git a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java index b33352664fab..dac43d936d0d 100644 --- a/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java +++ b/solr/core/src/java/org/apache/solr/cli/ToolRuntime.java @@ -16,7 +16,6 @@ */ package org.apache.solr.cli; -import org.apache.solr.cli.packagemanager.UserIO; import org.apache.solr.common.util.SuppressForbidden; /** @@ -25,21 +24,18 @@ * * @see ToolBase */ -public abstract class ToolRuntime implements UserIO { +public abstract class ToolRuntime { - @Override public abstract void print(String message); public abstract void println(String message); /** Print an error message, highlighted in red on terminals. */ - @Override public void printError(String message) { println(CLIUtils.RED + message + CLIUtils.RESET); } /** Print a success message, highlighted in green on terminals. */ - @Override public void printSuccess(String message) { println(CLIUtils.GREEN + message + CLIUtils.RESET); } diff --git a/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java index ae1717332a80..cfc6f2c29189 100644 --- a/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageManager.java @@ -38,6 +38,9 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import org.apache.solr.cli.CLIUtils; +import org.apache.solr.cli.SolrCLI; +import org.apache.solr.cli.ToolRuntime; import org.apache.solr.cli.packagemanager.SolrPackage.Command; import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; import org.apache.solr.cli.packagemanager.SolrPackage.Plugin; @@ -71,7 +74,7 @@ /** Handles most of the management of packages that are already installed in Solr. */ public class PackageManager implements Closeable { - final UserIO runtime; + final ToolRuntime runtime; final String solrUrl; final SolrClient solrClient; final SolrZkClient zkClient; @@ -80,7 +83,7 @@ public class PackageManager implements Closeable { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - public PackageManager(UserIO runtime, SolrClient solrClient, String solrUrl, String zkHost) { + public PackageManager(ToolRuntime runtime, SolrClient solrClient, String solrUrl, String zkHost) { this.runtime = runtime; this.solrUrl = solrUrl; this.solrClient = solrClient; @@ -99,33 +102,30 @@ public void close() throws IOException { } } - private void fail(String message) { - runtime.printError(message); - throw new SolrException(ErrorCode.BAD_REQUEST, message); - } - public void uninstall(String packageName, String version) throws IOException, SolrServerException { SolrPackageInstance packageInstance = getPackageInstance(packageName, version); if (packageInstance == null) { - fail( + runtime.printError( "Package " + packageName + ":" + version + " doesn't exist. Use the install command to install this package version first."); + runtime.exit(1); } // Make sure that this package instance is not deployed on any collection Map collectionsDeployedOn = getDeployedCollections(packageName); for (String collection : collectionsDeployedOn.keySet()) { if (version.equals(collectionsDeployedOn.get(collection))) { - fail( + runtime.printError( "Package " + packageName + " is currently deployed on collection: " + collection + ". Undeploy the package with undeploy --collections [,,...] before attempting to uninstall the package."); + runtime.exit(1); } } @@ -136,12 +136,13 @@ public void uninstall(String packageName, String version) SolrPackageInstance clusterPackageInstance = clusterPackages.get(clusterPackageName); if (packageName.equals(clusterPackageName) && version.equals(clusterPackageInstance.version)) { - fail( + runtime.printError( "Package " + packageName + "is currently deployed as a cluster-level plugin (" + clusterPackageInstance.getCustomData() + "). Undeploy the package with undeploy --collections [,,...] before uninstalling the package."); + runtime.exit(1); } } @@ -428,7 +429,7 @@ private Pair, List> deployCollectionPackage( .setRequiresCollection( false) /* Making a collection-request, but already baked into path */); boolean packageParamsExist = collectionParams.get("params") != null; - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, PackageUtils.getCollectionParamsPath(collection), getMapper() @@ -444,7 +445,7 @@ private Pair, List> deployCollectionPackage( // Set the package version in the collection's parameters try { - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, PackageUtils.getCollectionParamsPath(collection), "{set:{PKG_VERSIONS:{" @@ -459,7 +460,7 @@ private Pair, List> deployCollectionPackage( // If updating, refresh the package version for this to take effect if (isUpdate || pegToLatest) { try { - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, PackageUtils.PACKAGE_PATH, "{\"refresh\": \"" + packageInstance.name + "\"}"); @@ -502,7 +503,7 @@ private Pair, List> deployCollectionPackage( runtime.printSuccess("Executing " + payload + " for path:" + path); boolean shouldExecute = prompt(noprompt); if (shouldExecute) { - PackageUtils.postJsonToSolr(solrClient, path, payload); + SolrCLI.postJsonToSolr(solrClient, path, payload); } } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, ex); @@ -519,7 +520,7 @@ private Pair, List> deployCollectionPackage( // Set the package version in the collection's parameters try { - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, PackageUtils.getCollectionParamsPath(collection), "{update:{PKG_VERSIONS:{'" @@ -578,7 +579,7 @@ private boolean deployClusterPackage( String postBody = "{\"update\": " + Utils.toJSONString(pluginMeta) + "}"; runtime.printSuccess( "Posting " + postBody + " to " + PackageUtils.CLUSTER_PLUGINS_PATH); - PackageUtils.postJsonToSolr(solrClient, PackageUtils.CLUSTER_PLUGINS_PATH, postBody); + SolrCLI.postJsonToSolr(solrClient, PackageUtils.CLUSTER_PLUGINS_PATH, postBody); } catch (Exception e) { throw new SolrException(ErrorCode.SERVER_ERROR, e); } @@ -651,7 +652,7 @@ private boolean deployClusterPackage( runtime.printSuccess("Executing " + payload + " for path:" + path); boolean shouldExecute = prompt(noprompt); if (shouldExecute) { - PackageUtils.postJsonToSolr(solrClient, path, payload); + SolrCLI.postJsonToSolr(solrClient, path, payload); numberOfClusterPluginsDeployed++; } } catch (Exception ex) { @@ -679,9 +680,9 @@ private boolean prompt(boolean noprompt) { boolean shouldExecute = true; if (!noprompt) { // show a prompt asking user to execute the setup command for the plugin runtime.print( - UserIO.YELLOW + CLIUtils.YELLOW + "Execute this command. (If you choose no, you can manually deploy/undeploy this plugin later) (y/n): " - + UserIO.RESET); + + CLIUtils.RESET); try (Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8)) { String userInput = scanner.next(); if ("no".trim().equalsIgnoreCase(userInput) || "n".trim().equalsIgnoreCase(userInput)) { @@ -927,21 +928,23 @@ public void deploy( boolean pegToLatest = PackageUtils.LATEST.equals(version); SolrPackageInstance packageInstance = getPackageInstance(packageName, version); if (packageInstance == null) { - fail( + runtime.printError( "Package instance doesn't exist: " + packageName + ":" + version + ". Use install command to install this version first."); + runtime.exit(1); } Manifest manifest = packageInstance.manifest; if (!SolrVersion.LATEST.satisfies(manifest.versionConstraint)) { - fail( + runtime.printError( "Version incompatible! Solr version: " + SolrVersion.LATEST + ", package version constraint: " + manifest.versionConstraint); + runtime.exit(1); } boolean res = @@ -998,7 +1001,7 @@ public void undeploy( PackageUtils.resolve( cmd.path, deployedPackage.parameterDefaults, Map.of(), systemParams); runtime.printSuccess("Executing " + payload + " for path:" + path); - PackageUtils.postJsonToSolr(solrClient, path, payload); + SolrCLI.postJsonToSolr(solrClient, path, payload); } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, ex); } @@ -1055,7 +1058,7 @@ public void undeploy( collectionParameterOverrides, systemParams); runtime.printSuccess("Executing " + payload + " for path:" + path); - PackageUtils.postJsonToSolr(solrClient, path, payload); + SolrCLI.postJsonToSolr(solrClient, path, payload); } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, ex); } @@ -1071,11 +1074,11 @@ public void undeploy( // Set the package version in the collection's parameters try { // Is it better to "unset"? If so, build support in params API for "unset" - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, PackageUtils.getCollectionParamsPath(collection), "{set: {PKG_VERSIONS: {" + packageName + ": null}}}"); - PackageUtils.postJsonToSolr( + SolrCLI.postJsonToSolr( solrClient, PackageUtils.PACKAGE_PATH, "{\"refresh\": \"" + packageName + "\"}"); } catch (Exception ex) { throw new SolrException(ErrorCode.SERVER_ERROR, ex); diff --git a/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java index cdbc1b040257..35fdc24d97de 100644 --- a/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/PackageUtils.java @@ -34,12 +34,12 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.apache.commons.io.IOUtils; +import org.apache.solr.cli.CLIUtils; import org.apache.solr.cli.packagemanager.SolrPackage.Manifest; import org.apache.solr.client.api.model.UploadToFileStoreResponse; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.request.ContentWriterUpdateRequest; import org.apache.solr.client.solrj.request.FileStoreApi; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.response.InputStreamResponseParser; @@ -47,7 +47,6 @@ import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; -import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.Utils; import org.apache.solr.filestore.ClusterFileStore; import org.apache.solr.filestore.DistribFileStore; @@ -65,15 +64,6 @@ public class PackageUtils { public static String REPOSITORIES_ZK_PATH = "/repositories.json"; public static String CLUSTERPROPS_PATH = "/api/cluster/zk/data/clusterprops.json"; - private static final String JSON_CONTENT_TYPE = "application/json"; - - public static NamedList postJsonToSolr( - SolrClient solrClient, String updatePath, String jsonBody) throws Exception { - ContentWriterUpdateRequest req = new ContentWriterUpdateRequest(updatePath); - req.addContentWithType(jsonBody, JSON_CONTENT_TYPE); - return solrClient.request(req); - } - public static Configuration jsonPathConfiguration() { MappingProvider provider = new JacksonMappingProvider(); JsonProvider jsonProvider = new JacksonJsonProvider(); @@ -249,7 +239,7 @@ public static String resolve( /** Console print using green color */ public static void formatGreen(StringBuilder sb, Object message) { - format(sb, UserIO.GREEN, message); + format(sb, CLIUtils.GREEN, message); } public static void format(StringBuilder sb, Object message) { @@ -258,7 +248,7 @@ public static void format(StringBuilder sb, Object message) { public static void format(StringBuilder sb, String color, Object message) { if (color != null) { - sb.append(color + String.valueOf(message) + UserIO.RESET + "\n"); + sb.append(color + String.valueOf(message) + CLIUtils.RESET + "\n"); } else { sb.append(message + "\n"); } diff --git a/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java index 0da8b2444c53..64af782131f4 100644 --- a/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java +++ b/solr/core/src/java/org/apache/solr/cli/packagemanager/RepositoryManager.java @@ -36,6 +36,7 @@ import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; +import org.apache.solr.cli.ToolRuntime; import org.apache.solr.cli.packagemanager.SolrPackage.Artifact; import org.apache.solr.cli.packagemanager.SolrPackage.SolrPackageRelease; import org.apache.solr.client.api.util.SolrVersion; @@ -66,7 +67,7 @@ public class RepositoryManager { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private final PackageManager packageManager; - private final UserIO runtime; + private final ToolRuntime runtime; final SolrClient solrClient; diff --git a/solr/core/src/java/org/apache/solr/cli/packagemanager/UserIO.java b/solr/core/src/java/org/apache/solr/cli/packagemanager/UserIO.java deleted file mode 100644 index e00aae2cab4f..000000000000 --- a/solr/core/src/java/org/apache/solr/cli/packagemanager/UserIO.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.packagemanager; - -/** Console-facing output for package manager operations */ -@FunctionalInterface -public interface UserIO { - - String RED = "\u001B[31m"; - String GREEN = "\u001B[32m"; - String YELLOW = "\u001B[33m"; - String RESET = "\u001B[0m"; - - UserIO NONE = message -> {}; - - void print(String message); - - default void printSuccess(String message) { - print(GREEN + message + RESET + System.lineSeparator()); - } - - default void printError(String message) { - print(RED + message + RESET + System.lineSeparator()); - } -} diff --git a/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java b/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java index 504db7b263bb..2793af1641d7 100644 --- a/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java +++ b/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java @@ -21,6 +21,8 @@ import java.net.URL; import java.util.List; import java.util.Map; +import org.apache.solr.cli.CLITestHelper; +import org.apache.solr.cli.ToolRuntime; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; @@ -48,7 +50,8 @@ public void testWrongVerificationJPathIsThrown() throws IOException { SolrZkClient zkClient = cluster.getZkClient(); URL baseURLV2 = cluster.getJettySolrRunner(0).getBaseURLV2(); try (var solrClient = new HttpJettySolrClient.Builder(baseURLV2.toString()).build()) { - try (PackageManager manager = new StubPackageManager(solrClient, zkClient)) { + ToolRuntime runtime = new CLITestHelper.TestingRuntime(false); + try (PackageManager manager = new StubPackageManager(runtime, solrClient, zkClient)) { SolrPackage.Plugin plugin = new SolrPackage.Plugin(); if (random().nextBoolean()) { plugin.type = "cluster"; @@ -73,9 +76,9 @@ public void testWrongVerificationJPathIsThrown() throws IOException { } private static class StubPackageManager extends PackageManager { - public StubPackageManager(SolrClient solrClient, SolrZkClient zkClient) { + public StubPackageManager(ToolRuntime runtime, SolrClient solrClient, SolrZkClient zkClient) { super( - UserIO.NONE, + runtime, solrClient, SolrCloudTestCase.cluster.getJettySolrRunners().get(0).getBaseUrl().toString(), zkClient.getZkServerAddress()); From 250b26bdd8bb98022216f4d01a35b80383520d15 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 5 Oct 2026 10:09:19 +0530 Subject: [PATCH 21/26] cl update --- changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml b/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml index 1a4b7e65300e..276cf5861ff0 100644 --- a/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml +++ b/changelog/unreleased/SOLR-18234-solr-cli-detangle-core.yml @@ -1,5 +1,5 @@ title: - Stop PackageManager and test-framework from depending on CLI + Move packagemanager under CLI and stop test-framework from depending on CLI type: other authors: - name: Jalaz Kumar From 0609745975ea5d922958814abf686124f37be3e8 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 5 Oct 2026 10:12:23 +0530 Subject: [PATCH 22/26] one more ai review --- .../org/apache/solr/filestore/TestDistribFileStore.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java index 4d1ef7b6b7ac..7a6affe1b9e4 100644 --- a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java +++ b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java @@ -32,7 +32,6 @@ import java.util.concurrent.Callable; import java.util.function.Predicate; import org.apache.commons.codec.digest.DigestUtils; -import org.apache.solr.cli.packagemanager.PackageUtils; import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -330,7 +329,13 @@ public static T assertResponseValues( public static void uploadKey(byte[] bytes, String path, MiniSolrCloudCluster cluster) throws Exception { JettySolrRunner jetty = cluster.getRandomJetty(random()); - PackageUtils.uploadKey(bytes, path, jetty.getCoreContainer().getSolrHome()); + + FileStoreAPI.MetaData metaData = ClusterFileStore._createJsonMetaData(bytes, null); + DistribFileStore._persistToFile( + jetty.getCoreContainer().getSolrHome(), + path, + ByteBuffer.wrap(bytes), + ByteBuffer.wrap(Utils.toJSON(metaData))); final var syncReq = new FileStoreApi.SyncFile(path); final var syncRsp = syncReq.process(jetty.getSolrClient()); From 7705b3e2a751c457a56ca7ca3d24e32a6db863aa Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 5 Oct 2026 11:06:42 +0530 Subject: [PATCH 23/26] test corrected --- .../org/apache/solr/cloud/AbstractFullDistribZkTestBase.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java index 04300caf78d6..44b4e47ed20d 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java @@ -96,6 +96,7 @@ import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.TimeSource; import org.apache.solr.common.util.Utils; +import org.apache.solr.core.ConfigSetService; import org.apache.solr.core.CoreContainer; import org.apache.solr.core.Diagnostics; import org.apache.solr.core.MockDirectoryFactory; @@ -2220,7 +2221,9 @@ public static void copyConfigUp( Path configSetDir, String srcConfigSet, String dstConfigName, String zkAddr) throws Exception { - Path fullConfDir = configSetDir.resolve(srcConfigSet); + Path fullConfDir = + ConfigSetService.getConfigsetPath( + configSetDir.resolve(srcConfigSet).toString(), configSetDir.toString()); try (SolrZkClient zkClient = new SolrZkClient.Builder() .withUrl(zkAddr) From 3bc06557780eb4a90ba064412c860bfa0dc328e8 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 5 Oct 2026 11:09:44 +0530 Subject: [PATCH 24/26] minor --- .../org/apache/solr/cloud/AbstractFullDistribZkTestBase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java index 44b4e47ed20d..d774bb92efdc 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java @@ -2221,7 +2221,7 @@ public static void copyConfigUp( Path configSetDir, String srcConfigSet, String dstConfigName, String zkAddr) throws Exception { - Path fullConfDir = + Path confPath = ConfigSetService.getConfigsetPath( configSetDir.resolve(srcConfigSet).toString(), configSetDir.toString()); try (SolrZkClient zkClient = @@ -2229,7 +2229,7 @@ public static void copyConfigUp( .withUrl(zkAddr) .withTimeout(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS) .build()) { - zkClient.upConfig(fullConfDir, dstConfigName); + zkClient.upConfig(confPath, dstConfigName); } } From f8d8986a89e1807a3308a0b1c69266165ae5bae5 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 9 Oct 2026 16:06:46 +0530 Subject: [PATCH 25/26] import correct --- solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java index 9b8130227af1..0b4b35e7e07f 100644 --- a/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java +++ b/solr/core/src/java/org/apache/solr/cli/PackageSubCommand.java @@ -18,8 +18,8 @@ package org.apache.solr.cli; import org.apache.commons.cli.CommandLine; -import org.apache.solr.packagemanager.PackageManager; -import org.apache.solr.packagemanager.RepositoryManager; +import org.apache.solr.cli.packagemanager.PackageManager; +import org.apache.solr.cli.packagemanager.RepositoryManager; /** Shared picocli wiring for {@code bin/solr package leaves} */ @SuppressWarnings("UnnecessarilyFullyQualified") From d168c04ef39eec9bd9c1482f715ee459ed5a3422 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 9 Oct 2026 16:28:07 +0530 Subject: [PATCH 26/26] gradle cleanup put back on --- solr/test-framework/build.gradle | 4 +--- solr/test-framework/gradle.lockfile | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/solr/test-framework/build.gradle b/solr/test-framework/build.gradle index aa4114f3c960..ff9e87339db4 100644 --- a/solr/test-framework/build.gradle +++ b/solr/test-framework/build.gradle @@ -60,9 +60,7 @@ dependencies { implementation libs.slf4j.api implementation libs.apache.log4j.api implementation libs.apache.log4j.core - implementation libs.commonscli.commonscli - // Needed on the compile classpath because this project compiles against annotated org.apache.solr.cli types - implementation libs.picocli + implementation libs.opentelemetry.api implementation(libs.opentelemetry.exporter.prometheus) { transitive = false // most things don't want or already have diff --git a/solr/test-framework/gradle.lockfile b/solr/test-framework/gradle.lockfile index e980dd6d4e75..8802fb667e44 100644 --- a/solr/test-framework/gradle.lockfile +++ b/solr/test-framework/gradle.lockfile @@ -32,10 +32,10 @@ com.google.protobuf:protobuf-java:4.36.2=annotationProcessor,errorprone,testAnno com.j256.simplemagic:simplemagic:1.17=jarValidation,runtimeClasspath,testRuntimeClasspath com.jayway.jsonpath:json-path:3.0.0=jarValidation,runtimeClasspath,testRuntimeClasspath com.tdunning:t-digest:3.3=jarValidation,runtimeClasspath,testRuntimeClasspath -commons-cli:commons-cli:1.11.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-cli:commons-cli:1.11.0=jarValidation,runtimeClasspath,testRuntimeClasspath commons-codec:commons-codec:1.22.1=jarValidation,runtimeClasspath,testRuntimeClasspath commons-io:commons-io:2.22.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -info.picocli:picocli:4.7.6=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +info.picocli:picocli:4.7.6=jarValidation,runtimeClasspath,testRuntimeClasspath io.dropwizard.metrics:metrics-core:4.2.39=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor