From bae501076b09d138baabdce602b566a363797faa Mon Sep 17 00:00:00 2001 From: Arvind Kandpal Date: Mon, 1 Jun 2026 16:44:36 +0530 Subject: [PATCH] CASSANDRA-20876: Offline nodetool commands should not print network options in help - Added isOfflineCommand() to AbstractCommand to publicly expose whether a command requires a JMX connection - Updated CassandraCliHelpLayout to suppress JmxConnect options in help output for offline commands - Updated help snapshot for 'history' to reflect the correct output --- .../tools/nodetool/AbstractCommand.java | 17 +++++++++++++++ .../layout/CassandraCliHelpLayout.java | 14 ++++++++++++- test/resources/nodetool/help/history | 21 +------------------ 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/java/org/apache/cassandra/tools/nodetool/AbstractCommand.java b/src/java/org/apache/cassandra/tools/nodetool/AbstractCommand.java index 5c2530756392..feb15a54eecb 100644 --- a/src/java/org/apache/cassandra/tools/nodetool/AbstractCommand.java +++ b/src/java/org/apache/cassandra/tools/nodetool/AbstractCommand.java @@ -78,6 +78,23 @@ protected boolean shouldConnect() throws ExecutionException return true; } + /** + * Check if the command is designed to run locally without a JMX connection. + * @return {@code true} if it is an offline command, {@code false} otherwise. + */ + public boolean isOfflineCommand() + { + try + { + return !shouldConnect(); + } + catch (Exception e) + { + // Safe fallback: default to online if evaluation fails + return false; + } + } + /** * Execute the command using the supplied {@link NodeProbe} instance, which is already connected * to the node and ready to use. If the {@link NodeProbe} is not {@code null}, it is guaranteed that it diff --git a/src/java/org/apache/cassandra/tools/nodetool/layout/CassandraCliHelpLayout.java b/src/java/org/apache/cassandra/tools/nodetool/layout/CassandraCliHelpLayout.java index d99a7dd21bfa..7f6c1087cdf1 100644 --- a/src/java/org/apache/cassandra/tools/nodetool/layout/CassandraCliHelpLayout.java +++ b/src/java/org/apache/cassandra/tools/nodetool/layout/CassandraCliHelpLayout.java @@ -33,6 +33,7 @@ import org.apache.commons.lang3.StringUtils; +import org.apache.cassandra.tools.nodetool.AbstractCommand; import org.apache.cassandra.tools.nodetool.CommandUtils; import org.apache.cassandra.tools.nodetool.JmxConnect; import org.apache.cassandra.tools.nodetool.NodetoolCommand; @@ -257,6 +258,12 @@ private static List parentCommandOptionsWithJmxOpt if (commandSpec.helpCommand()) return Collections.emptyList(); + boolean shouldShowJmx = true; + if (commandSpec.userObject() instanceof AbstractCommand) + { + shouldShowJmx = !((AbstractCommand) commandSpec.userObject()).isOfflineCommand(); + } + List hierarhy = new LinkedList<>(); CommandLine.Model.CommandSpec curr; CommandLine.Model.CommandSpec command = commandSpec; @@ -271,11 +278,16 @@ private static List parentCommandOptionsWithJmxOpt { for (CommandLine.Model.OptionSpec option : spec.options()) { - // JmxConnect and NodetoolCommand options are always shown in the help output for backwards compatibility. + // JmxConnect options are shown for online commands only; NodetoolCommand options are always shown for backwards compatibility. if (option.userObject() instanceof Field && (((Field) option.userObject()).getDeclaringClass().equals(JmxConnect.class) || ((Field) option.userObject()).getDeclaringClass().equals(NodetoolCommand.class))) + { + if (((Field) option.userObject()).getDeclaringClass().equals(JmxConnect.class) && !shouldShowJmx) + continue; + options.add(option); + } else { if (option.hidden() || option.scopeType() == CommandLine.ScopeType.LOCAL) diff --git a/test/resources/nodetool/help/history b/test/resources/nodetool/help/history index 76eee5d057ab..dfe1b6e017f7 100644 --- a/test/resources/nodetool/help/history +++ b/test/resources/nodetool/help/history @@ -2,27 +2,8 @@ NAME nodetool history - Print previously executed nodetool commands SYNOPSIS - nodetool [(-h | --host )] [(-p | --port )] - [(-pw | --password )] - [(-pwf | --password-file )] - [(-u | --username )] history - [(-n | --number-of-commands )] + nodetool history [(-n | --number-of-commands )] OPTIONS - -h , --host - Node hostname or ip address - -n , --num , --number-of-commands Number of commands to print, defaults to 1000. - - -p , --port - Remote jmx agent port number - - -pw , --password - Remote jmx agent password - - -pwf , --password-file - Path to the JMX password file - - -u , --username - Remote jmx agent username